Diffstat (limited to 'src/build/builders/serde/deserialize_seed.rs')
| -rw-r--r-- | src/build/builders/serde/deserialize_seed.rs | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/build/builders/serde/deserialize_seed.rs b/src/build/builders/serde/deserialize_seed.rs new file mode 100644 index 0000000..614cbda --- /dev/null +++ b/src/build/builders/serde/deserialize_seed.rs @@ -0,0 +1,167 @@ +//! Adapter for serde's DeserializeSeed trait. + +use core::{marker::PhantomData, ops::ControlFlow}; + +use serde::{ + de::{DeserializeSeed, SeqAccess}, + forward_to_deserialize_any, Deserialize, Deserializer, +}; + +use crate::{ + any::static_wrapper::OwnedStatic, + any_trait, + protocol::{ + visitor::{Sequence, SequenceScope, Status, Value}, + ControlFlowFor, + }, + Builder as _, +}; + +pub enum Error<T> { + Pending(T), + Incomplete, + Custom, +} + +#[cfg(feature = "std")] +impl<T> std::error::Error for Error<T> {} + +impl<T> core::fmt::Debug for Error<T> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Pending(_) => write!(f, "Pending"), + Self::Incomplete => write!(f, "Incomplete"), + Self::Custom => write!(f, "Custom"), + } + } +} + +pub struct Builder<'ctx, T: DeserializeSeed<'ctx>>(Result<T::Value, Error<T>>); + +impl<'ctx, T: DeserializeSeed<'ctx>> crate::Builder<'ctx> for Builder<'ctx, T> { + type Error = Error<T>; + + type Value = T::Value; + + fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { + self + } + + fn build(self) -> Result<Self::Value, Self::Error> { + self.0 + } + + type Seed = T; + + fn from_seed(seed: Self::Seed) -> Self { + Self(Err(Error::Pending(seed))) + } +} + +any_trait! { + impl['a, 'ctx, T: DeserializeSeed<'ctx>] Builder<'ctx, T> = [ + dyn Value<'a, OwnedStatic<bool>> + 'a, + dyn Sequence<'ctx> + 'a, + ] +} + +enum InjectedValue<'a, 'ctx, T> { + Bool(bool), + Sequence(&'a mut dyn SequenceScope<'ctx>), + Extra(PhantomData<T>), +} + +impl<'a, 'ctx, T: DeserializeSeed<'ctx>> Value<'a, OwnedStatic<bool>> for Builder<'ctx, T> { + #[inline] + fn visit(&'a mut self, OwnedStatic(bool_value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); + let Err(Error::Pending(value)) = pending else { + todo!() + }; + + self.0 = value.deserialize(InjectedValue::Bool(bool_value)); + + if self.0.is_err() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } +} + +impl<'ctx, T: DeserializeSeed<'ctx>> Sequence<'ctx> for Builder<'ctx, T> { + #[inline] + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { + let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); + let Err(Error::Pending(value)) = pending else { + todo!() + }; + + self.0 = value.deserialize(InjectedValue::Sequence(scope)); + + if self.0.is_err() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } +} + +impl<T> core::fmt::Display for Error<T> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl<T> serde::de::Error for Error<T> { + fn custom<U>(_msg: U) -> Self + where + U: core::fmt::Display, + { + Error::Custom + } +} + +impl<'a, 'ctx, T> Deserializer<'ctx> for InjectedValue<'a, 'ctx, T> { + type Error = Error<T>; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'ctx>, + { + match self { + InjectedValue::Bool(value) => visitor.visit_bool(value), + InjectedValue::Sequence(scope) => visitor.visit_seq(SequenceAccess(scope, PhantomData)), + InjectedValue::Extra(_) => unreachable!(), + } + } + + forward_to_deserialize_any! { + <W: Visitor<'ctx>> + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +struct SequenceAccess<'a, 'ctx, T>(&'a mut dyn SequenceScope<'ctx>, PhantomData<T>); + +impl<'a, 'ctx, T> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx, T> { + type Error = Error<T>; + + fn next_element_seed<U>(&mut self, seed: U) -> Result<Option<U::Value>, Self::Error> + where + U: serde::de::DeserializeSeed<'ctx>, + { + let mut builder = Builder::from_seed(seed); + match self.0.next(builder.as_visitor()) { + ControlFlow::Continue(Status::Continue) => match builder.build() { + Ok(value) => Ok(Some(value)), + Err(error) => Err(Error::Incomplete), + }, + ControlFlow::Continue(Status::Done) => Ok(None), + ControlFlow::Break(()) => Err(Error::Incomplete), // use the one from builder + // if any. + } + } +} |