/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use serde::{ Deserializer, de::{self, MapAccess, Visitor}, }; use std::{fmt, marker::PhantomData}; pub trait DeserializeArguments<'de> { fn deserialize_argument(&mut self, key: &str, map: &mut A) -> Result<(), A::Error> where A: MapAccess<'de>; } impl<'de> DeserializeArguments<'de> for () { fn deserialize_argument(&mut self, _key: &str, map: &mut A) -> Result<(), A::Error> where A: MapAccess<'de>, { let _: de::IgnoredAny = map.next_value()?; Ok(()) } } pub(crate) fn deserialize_request<'de, T, D>(deserializer: D) -> Result where T: DeserializeArguments<'de> + Default, D: Deserializer<'de>, { struct DirectArgumentsVisitor { _phantom: PhantomData, } impl DirectArgumentsVisitor { fn new() -> Self { Self { _phantom: PhantomData, } } } impl<'de, T> Visitor<'de> for DirectArgumentsVisitor where T: DeserializeArguments<'de> + Default, { type Value = T; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a JMAP request object") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut target = T::default(); while let Some(key) = map.next_key::<&str>()? { target .deserialize_argument(key, &mut map) .map_err(de::Error::custom)?; } Ok(target) } } deserializer.deserialize_map(DirectArgumentsVisitor::::new()) }