tinc 0.2.1

GRPc to REST transcoding library
use super::{
    DeserializeContent, DeserializeHelper, Expected, IdentifiedValue, Identifier,
    IdentifierDeserializer, IdentifierFor, MapAccessValueDeserializer, SerdePathToken,
    TrackedError, Tracker, TrackerDeserializeIdentifier, TrackerDeserializer, TrackerFor,
    TrackerWrapper, report_tracked_error, set_irrecoverable,
};

pub trait TrackedStructDeserializer<'de>: Sized + TrackerFor + IdentifierFor + Expected
where
    Self::Tracker: TrackerWrapper,
{
    const DENY_UNKNOWN_FIELDS: bool = false;

    fn deserialize<D>(
        &mut self,
        field: Self::Identifier,
        tracker: &mut <Self::Tracker as TrackerWrapper>::Tracker,
        deserializer: D,
    ) -> Result<(), D::Error>
    where
        D: DeserializeContent<'de>;
}

impl<'de, T> TrackedStructDeserializer<'de> for Box<T>
where
    T: TrackedStructDeserializer<'de> + Default,
    T::Tracker: Tracker<Target = T> + Default + TrackerWrapper,
{
    const DENY_UNKNOWN_FIELDS: bool = T::DENY_UNKNOWN_FIELDS;

    #[inline(always)]
    fn deserialize<D>(
        &mut self,
        field: Self::Identifier,
        tracker: &mut <Self::Tracker as TrackerWrapper>::Tracker,
        deserializer: D,
    ) -> Result<(), D::Error>
    where
        D: DeserializeContent<'de>,
    {
        T::deserialize(self.as_mut(), field, tracker, deserializer)
    }
}

#[derive(Debug, Default)]
pub struct StructTracker<T>(pub T);

impl<T: Tracker> TrackerWrapper for StructTracker<T> {
    type Tracker = T;
}

impl<T> std::ops::Deref for StructTracker<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> std::ops::DerefMut for StructTracker<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl<T> Tracker for StructTracker<T>
where
    T: Tracker,
{
    type Target = T::Target;

    fn allow_duplicates(&self) -> bool {
        self.0.allow_duplicates()
    }
}

impl<'de, T, S> serde::de::DeserializeSeed<'de> for DeserializeHelper<'_, StructTracker<T>>
where
    T: Tracker<Target = S>,
    S: TrackedStructDeserializer<'de, Tracker = StructTracker<T>>,
{
    type Value = ();

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_struct(S::NAME, <S::Identifier as Identifier>::OPTIONS, self)
    }
}

impl<'de, T, S> TrackerDeserializer<'de> for StructTracker<T>
where
    T: Tracker<Target = S>,
    S: TrackedStructDeserializer<'de, Tracker = StructTracker<T>>,
{
    fn deserialize<D>(&mut self, value: &mut Self::Target, deserializer: D) -> Result<(), D::Error>
    where
        D: DeserializeContent<'de>,
    {
        deserializer.deserialize_seed(DeserializeHelper {
            tracker: self,
            value,
        })
    }
}

impl<'de, T, S> serde::de::Visitor<'de> for DeserializeHelper<'_, StructTracker<T>>
where
    T: Tracker<Target = S>,
    S: TrackedStructDeserializer<'de, Tracker = StructTracker<T>>,
{
    type Value = ();

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        S::expecting(formatter)
    }

    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::MapAccess<'de>,
    {
        while let Some(key) = map
            .next_key_seed(IdentifierDeserializer::<S::Identifier>::default())
            .inspect_err(|_| {
                set_irrecoverable();
            })?
        {
            let mut deserialized = false;
            match key {
                IdentifiedValue::Found(field) => {
                    let _token = SerdePathToken::push_field(field.name());
                    S::deserialize(
                        self.value,
                        field,
                        self.tracker,
                        MapAccessValueDeserializer {
                            map: &mut map,
                            deserialized: &mut deserialized,
                        },
                    )?;
                }
                IdentifiedValue::Unknown(field) => {
                    let _token = SerdePathToken::push_field(&field);
                    report_tracked_error(TrackedError::unknown_field(S::DENY_UNKNOWN_FIELDS))?;
                }
            }

            if !deserialized {
                map.next_value::<serde::de::IgnoredAny>().inspect_err(|_| {
                    set_irrecoverable();
                })?;
            }
        }

        Ok(())
    }
}

impl<'de, T> TrackerDeserializeIdentifier<'de> for StructTracker<T>
where
    T: Tracker,
    T::Target: IdentifierFor + TrackedStructDeserializer<'de, Tracker = Self>,
{
    fn deserialize<D>(
        &mut self,
        value: &mut Self::Target,
        identifier: <Self::Target as IdentifierFor>::Identifier,
        deserializer: D,
    ) -> Result<(), D::Error>
    where
        D: DeserializeContent<'de>,
    {
        T::Target::deserialize(value, identifier, self, deserializer)
    }
}