use imap_codec::imap_types::core::{Atom, NonEmptyVec}; use imap_codec::imap_types::extensions::enable::{CapabilityEnable, Utf8Kind}; use imap_codec::imap_types::response::Capability; use std::collections::HashSet; fn capability_unselect() -> Capability<'static> { Capability::try_from("UNSELECT").unwrap() } fn capability_condstore() -> Capability<'static> { Capability::try_from("CONDSTORE").unwrap() } fn capability_qresync() -> Capability<'static> { Capability::try_from("QRESYNC").unwrap() } #[derive(Debug, Clone)] pub struct ServerCapability(HashSet>); impl Default for ServerCapability { fn default() -> Self { Self(HashSet::from([ Capability::Imap4Rev1, Capability::Enable, Capability::Move, Capability::LiteralPlus, capability_unselect(), capability_condstore(), //capability_qresync(), ])) } } impl ServerCapability { pub fn to_vec(&self) -> NonEmptyVec> { self.0 .iter() .map(|v| v.clone()) .collect::>() .try_into() .unwrap() } #[allow(dead_code)] pub fn support(&self, cap: &Capability<'static>) -> bool { self.0.contains(cap) } } #[derive(Clone)] pub enum ClientStatus { NotSupportedByServer, Disabled, Enabled, } impl ClientStatus { pub fn is_enabled(&self) -> bool { matches!(self, Self::Enabled) } pub fn enable(&self) -> Self { match self { Self::Disabled => Self::Enabled, other => other.clone(), } } } pub struct ClientCapability { pub condstore: ClientStatus, pub utf8kind: Option, } impl ClientCapability { pub fn new(sc: &ServerCapability) -> Self { Self { condstore: match sc.0.contains(&capability_condstore()) { true => ClientStatus::Disabled, _ => ClientStatus::NotSupportedByServer, }, utf8kind: None, } } pub fn select_enable(&mut self, atoms: &[Atom]) { for at in atoms.iter() { if at.as_ref().to_uppercase() == "CONDSTORE" { self.condstore = self.condstore.enable(); } } } pub fn try_enable( &mut self, caps: &[CapabilityEnable<'static>], ) -> Vec> { let mut enabled = vec![]; for cap in caps { match cap { CapabilityEnable::CondStore if matches!(self.condstore, ClientStatus::Disabled) => { self.condstore = ClientStatus::Enabled; enabled.push(cap.clone()); } CapabilityEnable::Utf8(kind) if Some(kind) != self.utf8kind.as_ref() => { self.utf8kind = Some(kind.clone()); enabled.push(cap.clone()); } _ => (), } } enabled } }