use core::fmt;
use alloc::{string::String, vec};
use log::trace;
use secrecy::SecretString;
use thiserror::Error;
use crate::{
coroutine::*,
jmap_try,
rfc8620::{CORE_CAPABILITY, JmapSession, changes::*},
rfc8621::MAIL_CAPABILITY,
};
#[derive(Debug, Error)]
pub enum JmapEmailChangesError {
#[error("JMAP Email/changes failed: {0}")]
Changes(#[from] JmapChangesError),
}
#[derive(Clone, Debug, Default)]
pub struct JmapEmailChangesOptions {
pub max_changes: Option<u64>,
}
pub struct JmapEmailChanges {
state: State,
}
impl JmapEmailChanges {
pub fn new(
session: &JmapSession,
http_auth: &SecretString,
since_state: impl Into<String>,
opts: JmapEmailChangesOptions,
) -> Result<Self, JmapEmailChangesError> {
let account_id = session
.primary_accounts
.get(MAIL_CAPABILITY)
.cloned()
.unwrap_or_default();
let api_url = &session.api_url;
Ok(Self {
state: State::Changes(JmapChanges::new(
account_id,
http_auth,
api_url,
"Email/changes",
vec![CORE_CAPABILITY.into(), MAIL_CAPABILITY.into()],
since_state,
JmapChangesOptions {
max_changes: opts.max_changes,
},
)?),
})
}
}
impl JmapCoroutine for JmapEmailChanges {
type Yield = JmapYield;
type Return = Result<JmapChangesOutput, JmapEmailChangesError>;
fn resume(&mut self, arg: Option<&[u8]>) -> JmapCoroutineState<Self::Yield, Self::Return> {
trace!("Email/changes: {}", self.state);
match &mut self.state {
State::Changes(changes) => {
let out = jmap_try!(changes, arg);
JmapCoroutineState::Complete(Ok(out))
}
}
}
}
enum State {
Changes(JmapChanges),
}
impl fmt::Display for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Changes(_) => f.write_str("changes"),
}
}
}