aboutsummaryrefslogtreecommitdiff
path: root/src/mail
diff options
context:
space:
mode:
Diffstat (limited to 'src/mail')
-rw-r--r--src/mail/mailbox.rs2
-rw-r--r--src/mail/query.rs114
-rw-r--r--src/mail/snapshot.rs10
3 files changed, 100 insertions, 26 deletions
diff --git a/src/mail/mailbox.rs b/src/mail/mailbox.rs
index 306fd7d..2a0a24a 100644
--- a/src/mail/mailbox.rs
+++ b/src/mail/mailbox.rs
@@ -82,7 +82,7 @@ impl Mailbox {
self.mbox.read().await.fetch_full(id, message_key).await
}
- async fn frozen(self: &std::sync::Arc<Self>) -> super::snapshot::FrozenMailbox {
+ pub async fn frozen(self: &std::sync::Arc<Self>) -> super::snapshot::FrozenMailbox {
super::snapshot::FrozenMailbox::new(self.clone()).await
}
diff --git a/src/mail/query.rs b/src/mail/query.rs
index 631ad56..5beff37 100644
--- a/src/mail/query.rs
+++ b/src/mail/query.rs
@@ -10,10 +10,27 @@ use futures::stream::{FuturesUnordered, StreamExt};
pub struct Query<'a,'b> {
pub frozen: &'a FrozenMailbox,
pub emails: &'b [UniqueIdent],
+ pub scope: QueryScope,
+}
+
+pub enum QueryScope {
+ Index,
+ Partial,
+ Full,
}
impl<'a,'b> Query<'a,'b> {
- pub fn index(&self) -> Result<Vec<IndexResult>> {
+ pub async fn fetch(&self) -> Result<Vec<QueryResult>> {
+ match self.scope {
+ QueryScope::Index => self.index(),
+ QueryScope::Partial => self.partial().await,
+ QueryScope::Full => self.full().await,
+ }
+ }
+
+ // --- functions below are private *for reasons*
+
+ fn index(&self) -> Result<Vec<QueryResult>> {
self
.emails
.iter()
@@ -23,18 +40,18 @@ impl<'a,'b> Query<'a,'b> {
.snapshot
.table
.get(uuid)
- .map(|index| IndexResult { uuid: *uuid, index })
+ .map(|index| QueryResult::IndexResult { uuid: *uuid, index })
.ok_or(anyhow!("missing email in index"))
})
.collect::<Result<Vec<_>, _>>()
}
- pub async fn partial(&self) -> Result<Vec<PartialResult>> {
+ async fn partial(&self) -> Result<Vec<QueryResult>> {
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 })
+ .map(|(metadata, index)| index.into_partial(metadata).expect("index to be IndexResult"))
.collect::<Vec<_>>();
Ok(result)
}
@@ -43,18 +60,17 @@ impl<'a,'b> Query<'a,'b> {
/// 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>> {
+ async fn full(&self) -> Result<Vec<QueryResult>> {
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,
- })
+ let content = self.frozen.mailbox.fetch_full(
+ *meta.uuid(),
+ &meta.metadata().expect("meta to be PartialResult").message_key
+ ).await?;
+
+ Ok(meta.into_full(content).expect("meta to be PartialResult"))
})
.collect::<FuturesUnordered<_>>()
.collect::<Vec<_>>()
@@ -64,18 +80,66 @@ impl<'a,'b> Query<'a,'b> {
}
}
-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 enum QueryResult<'a> {
+ IndexResult {
+ uuid: UniqueIdent,
+ index: &'a IndexEntry,
+ },
+ PartialResult {
+ uuid: UniqueIdent,
+ index: &'a IndexEntry,
+ metadata: MailMeta,
+ },
+ FullResult {
+ uuid: UniqueIdent,
+ index: &'a IndexEntry,
+ metadata: MailMeta,
+ content: Vec<u8>,
+ }
}
-pub struct FullResult<'a> {
- pub uuid: UniqueIdent,
- pub index: &'a IndexEntry,
- pub metadata: MailMeta,
- pub content: Vec<u8>,
+impl<'a> QueryResult<'a> {
+ pub fn uuid(&self) -> &UniqueIdent {
+ match self {
+ Self::IndexResult { uuid, .. } => uuid,
+ Self::PartialResult { uuid, .. } => uuid,
+ Self::FullResult { uuid, .. } => uuid,
+ }
+ }
+
+ pub fn index(&self) -> &IndexEntry {
+ match self {
+ Self::IndexResult { index, .. } => index,
+ Self::PartialResult { index, .. } => index,
+ Self::FullResult { index, .. } => index,
+ }
+ }
+
+ pub fn metadata(&self) -> Option<&MailMeta> {
+ match self {
+ Self::IndexResult { .. } => None,
+ Self::PartialResult { metadata, .. } => Some(metadata),
+ Self::FullResult { metadata, .. } => Some(metadata),
+ }
+ }
+
+ pub fn content(&self) -> Option<&[u8]> {
+ match self {
+ Self::FullResult { content, .. } => Some(content),
+ _ => None,
+ }
+ }
+
+ fn into_partial(self, metadata: MailMeta) -> Option<Self> {
+ match self {
+ Self::IndexResult { uuid, index } => Some(Self::PartialResult { uuid, index, metadata }),
+ _ => None,
+ }
+ }
+
+ fn into_full(self, content: Vec<u8>) -> Option<Self> {
+ match self {
+ Self::PartialResult { uuid, index, metadata } => Some(Self::FullResult { uuid, index, metadata, content }),
+ _ => None,
+ }
+ }
}
diff --git a/src/mail/snapshot.rs b/src/mail/snapshot.rs
index 54bec64..c3145b4 100644
--- a/src/mail/snapshot.rs
+++ b/src/mail/snapshot.rs
@@ -4,6 +4,8 @@ use anyhow::Result;
use super::mailbox::Mailbox;
use super::uidindex::UidIndex;
+use super::unique_ident::UniqueIdent;
+use super::query::{Query, QueryScope};
/// A Frozen Mailbox has a snapshot of the current mailbox
/// state that is desynchronized with the real mailbox state.
@@ -49,4 +51,12 @@ impl FrozenMailbox {
old_snapshot
}
+
+ pub fn query<'a, 'b>(&'a self, uuids: &'b [UniqueIdent], scope: QueryScope) -> Query<'a, 'b> {
+ Query {
+ frozen: self,
+ emails: uuids,
+ scope,
+ }
+ }
}