aboutsummaryrefslogtreecommitdiff
path: root/src/imap/index.rs
diff options
context:
space:
mode:
authorQuentin <quentin@dufour.io>2024-01-06 10:38:37 +0000
committerQuentin <quentin@dufour.io>2024-01-06 10:38:37 +0000
commit44ca458c5cf666246e472dea9be70b745a130e8c (patch)
treeb78cca747e5c2bc004cb93b93536623f7abb6ef5 /src/imap/index.rs
parentbcf6de83419b405fea95b740869f98d43586ea7c (diff)
parent53dbf82cbce3cb17cbcffd09558677faf8702f54 (diff)
downloadaerogramme-44ca458c5cf666246e472dea9be70b745a130e8c.tar.gz
aerogramme-44ca458c5cf666246e472dea9be70b745a130e8c.zip
Merge pull request 'Aerogramme refactoring' (#57) from feat/more-imap-qol into main
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/aerogramme/pulls/57
Diffstat (limited to 'src/imap/index.rs')
-rw-r--r--src/imap/index.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/imap/index.rs b/src/imap/index.rs
new file mode 100644
index 0000000..01dd2ef
--- /dev/null
+++ b/src/imap/index.rs
@@ -0,0 +1,95 @@
+use std::num::NonZeroU32;
+
+use anyhow::{anyhow, bail, Result};
+use imap_codec::imap_types::sequence::{self, SequenceSet};
+
+use crate::mail::uidindex::{ImapUid, UidIndex};
+use crate::mail::unique_ident::UniqueIdent;
+
+pub struct Index<'a>(pub &'a UidIndex);
+impl<'a> Index<'a> {
+ pub fn fetch(
+ self: &Index<'a>,
+ sequence_set: &SequenceSet,
+ by_uid: bool,
+ ) -> Result<Vec<MailIndex<'a>>> {
+ let mail_vec = self
+ .0
+ .idx_by_uid
+ .iter()
+ .map(|(uid, uuid)| (*uid, *uuid))
+ .collect::<Vec<_>>();
+
+ let mut mails = vec![];
+
+ if by_uid {
+ if mail_vec.is_empty() {
+ return Ok(vec![]);
+ }
+ let iter_strat = sequence::Strategy::Naive {
+ largest: mail_vec.last().unwrap().0,
+ };
+
+ let mut i = 0;
+ for uid in sequence_set.iter(iter_strat) {
+ while mail_vec.get(i).map(|mail| mail.0 < uid).unwrap_or(false) {
+ i += 1;
+ }
+ if let Some(mail) = mail_vec.get(i) {
+ if mail.0 == uid {
+ mails.push(MailIndex {
+ i: NonZeroU32::try_from(i as u32 + 1).unwrap(),
+ uid: mail.0,
+ uuid: mail.1,
+ flags: self
+ .0
+ .table
+ .get(&mail.1)
+ .ok_or(anyhow!("mail is missing from index"))?
+ .1
+ .as_ref(),
+ });
+ }
+ } else {
+ break;
+ }
+ }
+ } else {
+ if mail_vec.is_empty() {
+ bail!("No such message (mailbox is empty)");
+ }
+
+ let iter_strat = sequence::Strategy::Naive {
+ largest: NonZeroU32::try_from((mail_vec.len()) as u32).unwrap(),
+ };
+
+ for i in sequence_set.iter(iter_strat) {
+ if let Some(mail) = mail_vec.get(i.get() as usize - 1) {
+ mails.push(MailIndex {
+ i,
+ uid: mail.0,
+ uuid: mail.1,
+ flags: self
+ .0
+ .table
+ .get(&mail.1)
+ .ok_or(anyhow!("mail is missing from index"))?
+ .1
+ .as_ref(),
+ });
+ } else {
+ bail!("No such mail: {}", i);
+ }
+ }
+ }
+
+ Ok(mails)
+ }
+}
+
+pub struct MailIndex<'a> {
+ pub i: NonZeroU32,
+ pub uid: ImapUid,
+ pub uuid: UniqueIdent,
+ pub flags: &'a Vec<String>,
+}