Diffstat (limited to 'src/build/builders/serde/deserialize_seed.rs')
-rw-r--r--src/build/builders/serde/deserialize_seed.rs167
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.
+ }
+ }
+}