aboutsummaryrefslogtreecommitdiff
path: root/src/mail/query.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mail/query.rs')
-rw-r--r--src/mail/query.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/mail/query.rs b/src/mail/query.rs
index e69de29..631ad56 100644
--- a/src/mail/query.rs
+++ b/src/mail/query.rs
@@ -0,0 +1,81 @@
+use anyhow::{Result, anyhow};
+use super::mailbox::MailMeta;
+use super::snapshot::FrozenMailbox;
+use super::unique_ident::UniqueIdent;
+use super::uidindex::IndexEntry;
+use futures::stream::{FuturesUnordered, StreamExt};
+
+/// Query is in charge of fetching efficiently
+/// requested data for a list of emails
+pub struct Query<'a,'b> {
+ pub frozen: &'a FrozenMailbox,
+ pub emails: &'b [UniqueIdent],
+}
+
+impl<'a,'b> Query<'a,'b> {
+ pub fn index(&self) -> Result<Vec<IndexResult>> {
+ self
+ .emails
+ .iter()
+ .map(|uuid| {
+ self
+ .frozen
+ .snapshot
+ .table
+ .get(uuid)
+ .map(|index| IndexResult { uuid: *uuid, index })
+ .ok_or(anyhow!("missing email in index"))
+ })
+ .collect::<Result<Vec<_>, _>>()
+ }
+
+ pub async fn partial(&self) -> Result<Vec<PartialResult>> {
+ let meta = self.frozen.mailbox.fetch_meta(self.emails).await?;
+ let result = meta
+ .into_iter()
+ .zip(self.index()?)
+ .map(|(metadata, index)| PartialResult { uuid: index.uuid, index: index.index, metadata })
+ .collect::<Vec<_>>();
+ Ok(result)
+ }
+
+ /// @FIXME WARNING: THIS CAN ALLOCATE A LOT OF MEMORY
+ /// AND GENERATE SO MUCH NETWORK TRAFFIC.
+ /// THIS FUNCTION SHOULD BE REWRITTEN, FOR EXAMPLE WITH
+ /// SOMETHING LIKE AN ITERATOR
+ pub async fn full(&self) -> Result<Vec<FullResult>> {
+ let meta_list = self.partial().await?;
+ meta_list
+ .into_iter()
+ .map(|meta| async move {
+ let content = self.frozen.mailbox.fetch_full(meta.uuid, &meta.metadata.message_key).await?;
+ Ok(FullResult {
+ uuid: meta.uuid,
+ index: meta.index,
+ metadata: meta.metadata,
+ content,
+ })
+ })
+ .collect::<FuturesUnordered<_>>()
+ .collect::<Vec<_>>()
+ .await
+ .into_iter()
+ .collect::<Result<Vec<_>, _>>()
+ }
+}
+
+pub struct IndexResult<'a> {
+ pub uuid: UniqueIdent,
+ pub index: &'a IndexEntry,
+}
+pub struct PartialResult<'a> {
+ pub uuid: UniqueIdent,
+ pub index: &'a IndexEntry,
+ pub metadata: MailMeta,
+}
+pub struct FullResult<'a> {
+ pub uuid: UniqueIdent,
+ pub index: &'a IndexEntry,
+ pub metadata: MailMeta,
+ pub content: Vec<u8>,
+}