use alloc::{vec, vec::Vec};
use io_jmap::{
coroutine::{JmapCoroutine, JmapCoroutineState, JmapYield},
rfc8620::JmapSession,
rfc8621::mailbox::{
JmapMailbox as JmapMailboxObject, JmapMailboxProperty,
query::{
JmapMailboxQuery, JmapMailboxQueryError, JmapMailboxQueryOptions,
JmapMailboxQueryOutput,
},
},
};
use log::trace;
use secrecy::SecretString;
use thiserror::Error;
use crate::mailbox::types::Mailbox;
#[derive(Debug, Error)]
pub enum JmapMailboxListError {
#[error(transparent)]
Query(#[from] JmapMailboxQueryError),
}
pub struct JmapMailboxList {
inner: JmapMailboxQuery,
}
impl JmapMailboxList {
pub fn new(
session: &JmapSession,
http_auth: &SecretString,
with_counts: bool,
) -> Result<Self, JmapMailboxListError> {
trace!("prepare JMAP mailbox listing (with_counts={with_counts})");
let properties = if with_counts {
vec![
JmapMailboxProperty::Id,
JmapMailboxProperty::Name,
JmapMailboxProperty::TotalEmails,
JmapMailboxProperty::UnreadEmails,
]
} else {
vec![JmapMailboxProperty::Id, JmapMailboxProperty::Name]
};
let opts = JmapMailboxQueryOptions {
properties: Some(properties),
..Default::default()
};
Ok(Self {
inner: JmapMailboxQuery::new(session, http_auth, opts)?,
})
}
}
fn mailbox_from(mailbox: JmapMailboxObject) -> Mailbox {
Mailbox {
id: mailbox.id.unwrap_or_default(),
name: mailbox.name.unwrap_or_default(),
total: Some(u64::from(mailbox.total_emails)),
unread: Some(u64::from(mailbox.unread_emails)),
}
}
impl JmapCoroutine for JmapMailboxList {
type Yield = JmapYield;
type Return = Result<Vec<Mailbox>, JmapMailboxListError>;
fn resume(&mut self, bytes: Option<&[u8]>) -> JmapCoroutineState<Self::Yield, Self::Return> {
match self.inner.resume(bytes) {
JmapCoroutineState::Yielded(y) => JmapCoroutineState::Yielded(y),
JmapCoroutineState::Complete(Ok(JmapMailboxQueryOutput { mailboxes, .. })) => {
let mailboxes = mailboxes.into_iter().map(mailbox_from).collect();
JmapCoroutineState::Complete(Ok(mailboxes))
}
JmapCoroutineState::Complete(Err(err)) => JmapCoroutineState::Complete(Err(err.into())),
}
}
}