/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use ahash::AHashMap; use jmap_tools::Property; use serde::{ Deserialize, Deserializer, Serialize, Serializer, de::{self, MapAccess, Visitor}, }; use std::{borrow::Cow, fmt, str::FromStr}; pub mod availability; pub mod changes; pub mod copy; pub mod get; pub mod import; pub mod lookup; pub mod parse; pub mod query; pub mod query_changes; pub mod search_snippet; pub mod set; pub mod upload; pub mod validate; #[inline(always)] fn ahash_is_empty(map: &AHashMap) -> bool { map.is_empty() } #[derive(Debug, Clone)] #[repr(transparent)] pub struct PropertyWrapper(pub T); impl From for PropertyWrapper { fn from(value: T) -> Self { Self(value) } } impl Serialize for PropertyWrapper { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(self.0.to_cow().as_ref()) } } pub(crate) struct JmapDict(pub Vec); struct JmapDictVisitor<'de, T: FromStr> { marker: std::marker::PhantomData<&'de T>, } impl<'de, T: FromStr> Visitor<'de> for JmapDictVisitor<'de, T> { type Value = JmapDict; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a map") } fn visit_map(self, mut access: M) -> Result where M: MapAccess<'de>, { let mut vec = Vec::with_capacity(3); while let Some(key) = access.next_key::>()? { let key = T::from_str(&key).map_err(|_| de::Error::custom("invalid dictionary key"))?; if access.next_value::>()?.unwrap_or(false) { vec.push(key); } } Ok(JmapDict(vec)) } } impl<'de, T: FromStr + 'static> Deserialize<'de> for JmapDict { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_map(JmapDictVisitor { marker: std::marker::PhantomData, }) } }