Diffstat (limited to 'src/build/builders/serde/deserialize.rs')
| -rw-r--r-- | src/build/builders/serde/deserialize.rs | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/build/builders/serde/deserialize.rs b/src/build/builders/serde/deserialize.rs new file mode 100644 index 0000000..1c24e6e --- /dev/null +++ b/src/build/builders/serde/deserialize.rs @@ -0,0 +1,142 @@ +//! Adapter for serde's Deserialize trait. + +use core::ops::ControlFlow; + +use serde::{de::SeqAccess, forward_to_deserialize_any, Deserialize, Deserializer}; + +use crate::{ + any::static_wrapper::OwnedStatic, + any_trait, + protocol::{ + visitor::{Sequence, SequenceScope, Status, Value}, + ControlFlowFor, + }, + Builder as _, +}; + +#[derive(Debug)] +pub enum Error { + Incomplete, + Custom, +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +pub struct Builder<T>(Result<T, Error>); + +impl<'ctx, T: Deserialize<'ctx>> crate::Builder<'ctx> for Builder<T> { + type Error = Error; + + type Value = T; + + fn as_visitor(&mut self) -> &mut crate::protocol::Visitor<'_, 'ctx> { + self + } + + fn build(self) -> Result<Self::Value, Self::Error> { + self.0 + } + + type Seed = (); + + fn from_seed(seed: Self::Seed) -> Self { + Self(Err(Error::Incomplete)) + } +} + +any_trait! { + impl['a, 'ctx, T: Deserialize<'ctx>] Builder<T> = [ + dyn Value<'a, OwnedStatic<bool>> + 'a, + dyn Sequence<'ctx> + 'a, + ] +} + +enum InjectedValue<'a, 'ctx> { + Bool(bool), + Sequence(&'a mut dyn SequenceScope<'ctx>), +} + +impl<'a, 'ctx, T: Deserialize<'ctx>> Value<'a, OwnedStatic<bool>> for Builder<T> { + #[inline] + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + self.0 = T::deserialize(InjectedValue::Bool(value)); + + if self.0.is_err() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } +} + +impl<'ctx, T: Deserialize<'ctx>> Sequence<'ctx> for Builder<T> { + #[inline] + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { + self.0 = T::deserialize(InjectedValue::Sequence(scope)); + + if self.0.is_err() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } +} + +impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl serde::de::Error for Error { + fn custom<T>(_msg: T) -> Self + where + T: core::fmt::Display, + { + Error::Custom + } +} + +impl<'a, 'ctx> Deserializer<'ctx> for InjectedValue<'a, 'ctx> { + type Error = Error; + + 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)), + } + } + + 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>(&'a mut dyn SequenceScope<'ctx>); + +impl<'a, 'ctx> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx> { + type Error = Error; + + fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> + where + T: serde::de::DeserializeSeed<'ctx>, + { + let mut builder = super::deserialize_seed::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. + } + } +} |