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