added serde deserialize builder
| -rw-r--r-- | Cargo.lock | 24 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/any.rs | 6 | ||||
| -rw-r--r-- | src/build.rs | 39 | ||||
| -rw-r--r-- | src/build/builders.rs | 3 | ||||
| -rw-r--r-- | src/build/builders/core/array.rs | 53 | ||||
| -rw-r--r-- | src/build/builders/core/bool.rs | 14 | ||||
| -rw-r--r-- | src/build/builders/serde.rs | 2 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize.rs | 142 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize_seed.rs | 167 | ||||
| -rw-r--r-- | src/walk/walkers/core/array.rs | 19 | ||||
| -rw-r--r-- | tests/demo.rs | 21 | ||||
| -rw-r--r-- | tests/hook.rs | 0 |
13 files changed, 438 insertions, 55 deletions
@@ -132,6 +132,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -407,6 +413,12 @@ dependencies = [ ] [[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -433,6 +445,17 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] name = "signal-hook-registry" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -518,6 +541,7 @@ dependencies = [ "macro_rules_attribute", "proptest", "serde", + "serde_json", "tokio", ] @@ -7,7 +7,7 @@ edition = "2021" serde = { version = "1.0", default-features = false, optional = true } [features] -default = [] +default = ["std", "serde"] std = ["alloc", "serde?/std"] alloc = ["serde?/alloc"] serde = ["dep:serde"] @@ -15,6 +15,7 @@ serde = ["dep:serde"] [dev-dependencies] macro_rules_attribute = "0.2.0" proptest = "1.4.0" +serde_json = "1.0.114" tokio = { version = "1.36.0", features = ["full"] } [profile.test.package.proptest] @@ -400,9 +400,11 @@ impl<'lt> dyn AnyTrait<'lt> + '_ { #[macro_export] macro_rules! any_trait { { - impl[$a:lifetime, $lt:lifetime $($generic:tt)*] $name:ty = [$($protocol:ty),* $(,)?]; + impl[$a:lifetime, $lt:lifetime $($generic:tt)*] $name:ty = [$($protocol:ty),* $(,)?] $(where $($bound:tt)*)? } => { - impl<$lt $($generic)*> $crate::any::AnyTrait<$lt> for $name { + impl<$lt $($generic)*> $crate::any::AnyTrait<$lt> for $name + $(where $($bound)*)? + { #[inline] fn upcast_to_id<$a>( &$a self, diff --git a/src/build.rs b/src/build.rs index f0bb597..b17413a 100644 --- a/src/build.rs +++ b/src/build.rs @@ -24,13 +24,17 @@ pub trait Build<'ctx>: Sized { /// the builder with data from it's walk. /// - Call [`Self::build()`] to finish building the value and get any errors /// that happened during filling it with data. -pub trait Builder<'ctx>: Default { +pub trait Builder<'ctx> { + type Seed; + /// Error that can happen during filling the builder with data. type Error; /// Type to be built. type Value; + fn from_seed(seed: Self::Seed) -> Self; + /// Get the builder as a visitor that a walker can use. /// /// This is expected to just be `self`. @@ -43,6 +47,19 @@ pub trait Builder<'ctx>: Default { fn build(self) -> Result<Self::Value, Self::Error>; } +pub trait DefaultBuilder<'ctx>: Builder<'ctx> { + fn default() -> Self; +} + +impl<'ctx, B: Builder<'ctx>> DefaultBuilder<'ctx> for B +where + B::Seed: Default, +{ + fn default() -> Self { + Self::from_seed(Default::default()) + } +} + #[derive(Debug)] pub enum BuildError<B, W> { Builder(B), @@ -52,8 +69,11 @@ pub enum BuildError<B, W> { #[inline] pub fn build<'ctx, T: Build<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( walker: W, -) -> Result<T, BuildError<<<T as Build<'ctx>>::Builder as Builder<'ctx>>::Error, W::Error>> { - let mut builder = T::Builder::default(); +) -> Result<T, BuildError<<<T as Build<'ctx>>::Builder as Builder<'ctx>>::Error, W::Error>> +where + <<T as Build<'ctx>>::Builder as Builder<'ctx>>::Seed: Default, +{ + let mut builder = T::Builder::from_seed(Default::default()); if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { return Err(BuildError::Walker(err)); @@ -64,8 +84,11 @@ pub fn build<'ctx, T: Build<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( pub fn build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( walker: W, -) -> Result<B::Value, BuildError<B::Error, W::Error>> { - let mut builder = B::default(); +) -> Result<B::Value, BuildError<B::Error, W::Error>> +where + <B as Builder<'ctx>>::Seed: Default, +{ + let mut builder = B::from_seed(Default::default()); if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor()) { return Err(BuildError::Walker(err)); @@ -78,7 +101,11 @@ pub fn build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = SyncEffect>>( use crate::protocol::AsyncEffect; #[cfg(feature = "alloc")] -pub async fn async_build_with<'ctx, B: Builder<'ctx>, W: Walker<'ctx, Effect = AsyncEffect>>( +pub async fn async_build_with< + 'ctx, + B: DefaultBuilder<'ctx>, + W: Walker<'ctx, Effect = AsyncEffect>, +>( walker: W, ) -> Result<B::Value, BuildError<B::Error, W::Error>> { let mut builder = B::default(); diff --git a/src/build/builders.rs b/src/build/builders.rs index 5a7ca06..f5eac87 100644 --- a/src/build/builders.rs +++ b/src/build/builders.rs @@ -1 +1,4 @@ pub mod core; + +#[cfg(feature = "serde")] +pub mod serde; diff --git a/src/build/builders/core/array.rs b/src/build/builders/core/array.rs index f3311e5..8638fae 100644 --- a/src/build/builders/core/array.rs +++ b/src/build/builders/core/array.rs @@ -6,6 +6,7 @@ use crate::{ visitor::{Sequence, SequenceScope, Status}, ControlFlowFor, Effect, }, + DefaultBuilder, }; #[cfg(feature = "alloc")] @@ -17,6 +18,7 @@ use alloc::boxed::Box; impl<'ctx, T, const N: usize> crate::Build<'ctx> for [T; N] where T: crate::Build<'ctx>, + <T as crate::Build<'ctx>>::Builder: DefaultBuilder<'ctx>, { type Builder = Builder<'ctx, T::Builder, N>; } @@ -33,17 +35,9 @@ pub struct Builder<'ctx, B: crate::Builder<'ctx>, const N: usize> { item_err: Option<(usize, B::Error)>, } -impl<'ctx, B: crate::Builder<'ctx>, const N: usize> Default for Builder<'ctx, B, N> { - fn default() -> Self { - Self { - array: MaybeUninit::uninit(), - index: 0, - item_err: None, - } - } -} - -impl<'ctx, B: crate::Builder<'ctx>, const N: usize> crate::Builder<'ctx> for Builder<'ctx, B, N> { +impl<'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize> crate::Builder<'ctx> + for Builder<'ctx, B, N> +{ type Error = ArrayError<B::Error>; type Value = [B::Value; N]; @@ -63,26 +57,34 @@ impl<'ctx, B: crate::Builder<'ctx>, const N: usize> crate::Builder<'ctx> for Bui Ok(unsafe { self.array.assume_init() }) } } -} -#[cfg(not(feature = "alloc"))] -any_trait! { - impl['a, 'ctx, B: crate::Builder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ - dyn Sequence<'ctx> + 'a, - ]; + type Seed = (); + + fn from_seed(seed: Self::Seed) -> Self { + Self { + array: MaybeUninit::uninit(), + index: 0, + item_err: None, + } + } } -#[cfg(feature = "alloc")] +// #[cfg(not(feature = "alloc"))] any_trait! { - impl['a, 'ctx, B: crate::Builder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ + impl['a, 'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ dyn Sequence<'ctx> + 'a, - dyn Sequence<'ctx, AsyncEffect> + 'a, - ]; + ] } -impl<'ctx, B: crate::Builder<'ctx>, const N: usize> Sequence<'ctx> - for Builder<'ctx, B, N> -{ +// #[cfg(feature = "alloc")] +// any_trait! { +// impl['a, 'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize] Builder<'ctx, B, N> = [ +// dyn Sequence<'ctx> + 'a, +// dyn Sequence<'ctx, AsyncEffect> + 'a, +// ] +// } + +impl<'ctx, B: crate::DefaultBuilder<'ctx>, const N: usize> Sequence<'ctx> for Builder<'ctx, B, N> { #[inline] fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a> { loop { @@ -108,7 +110,8 @@ impl<'ctx, B: crate::Builder<'ctx>, const N: usize> Sequence<'ctx> // .write(value) // }; unsafe { - let ptr = (self.array.as_mut_ptr() as *mut B::Value).offset(self.index as _); + let ptr = + (self.array.as_mut_ptr() as *mut B::Value).offset(self.index as _); core::ptr::write(ptr, value); } // std::ptr::write(&mut self.array diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs index ebf628c..56ef873 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -17,12 +17,6 @@ pub enum Error { pub struct Builder(Option<bool>); -impl<'ctx> Default for Builder { - fn default() -> Self { - Self(None) - } -} - impl<'ctx> crate::Builder<'ctx> for Builder { type Error = Error; @@ -36,12 +30,18 @@ impl<'ctx> crate::Builder<'ctx> for Builder { fn build(self) -> Result<Self::Value, Self::Error> { self.0.ok_or(Error::Incomplete) } + + type Seed = (); + + fn from_seed(seed: Self::Seed) -> Self { + Self(None) + } } any_trait! { impl['a, 'ctx] Builder = [ dyn Value<'a, OwnedStatic<bool>> + 'a, - ]; + ] } impl<'a> Value<'a, OwnedStatic<bool>> for Builder { diff --git a/src/build/builders/serde.rs b/src/build/builders/serde.rs new file mode 100644 index 0000000..1b521bb --- /dev/null +++ b/src/build/builders/serde.rs @@ -0,0 +1,2 @@ +pub mod deserialize; +pub mod deserialize_seed; 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. + } + } +} 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. + } + } +} diff --git a/src/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs index 2709135..571787c 100644 --- a/src/walk/walkers/core/array.rs +++ b/src/walk/walkers/core/array.rs @@ -10,9 +10,9 @@ use crate::{ }, }; -impl<'ctx, T: crate::Walk<'ctx>, const N: usize> crate::Walk<'ctx> for [T; N] +impl<'ctx, T: crate::Walk<'ctx>, const N: usize> crate::Walk<'ctx> for [T; N] where - <T as crate::Walk<'ctx>>::Walker: crate::Walker<'ctx, Effect = SyncEffect> + <T as crate::Walk<'ctx>>::Walker: crate::Walker<'ctx, Effect = SyncEffect>, { type Walker = Walker<'ctx, T, N, T::Walker>; } @@ -41,8 +41,8 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx> + From<T>> From<[T; N]> } } -impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> crate::Walker<'ctx> - for Walker<'ctx, T, N, W> +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> + crate::Walker<'ctx> for Walker<'ctx, T, N, W> { type Effect = SyncEffect; @@ -67,8 +67,8 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From } } -impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> SequenceScope<'ctx> - for Walker<'ctx, T, N, W> +impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> + SequenceScope<'ctx> for Walker<'ctx, T, N, W> { #[inline] fn next<'a>( @@ -79,7 +79,12 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From return ControlFlow::Continue(Status::Done); } - let value = unsafe { self.array.get_unchecked_mut(self.index).take().unwrap_unchecked() }; + let value = unsafe { + self.array + .get_unchecked_mut(self.index) + .take() + .unwrap_unchecked() + }; self.index += 1; let walker = W::from(value); diff --git a/tests/demo.rs b/tests/demo.rs index 6db1559..9812ef6 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -25,6 +25,11 @@ fn demo() { let s = build_with::<array::Builder<'_, JsonLike, 3>, _>(into_walker(&a)).unwrap(); dbg!(s); + use treaty::builders::serde::deserialize::Builder as SerdeBuilder; + + let x = build_with::<SerdeBuilder<serde_json::Value>, _>(into_walker(&a)).unwrap(); + dbg!(x); + // let s = build_with::<JsonLike, _>(into_walker(a)).unwrap(); todo!(); @@ -98,13 +103,9 @@ fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: &'a mut Visitor<'a, 'ctx>) { if let Some(value) = self.0.pop_front() { into_walker(value).walk(visitor); - ControlFlow::Continue( - treaty::protocol::visitor::Status::Continue, - ) + ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) } else { - ControlFlow::Continue( - treaty::protocol::visitor::Status::Done, - ) + ControlFlow::Continue(treaty::protocol::visitor::Status::Done) } } } @@ -132,13 +133,19 @@ impl<'ctx> Builder<'ctx> for JsonLike { fn build(self) -> Result<Self::Value, Self::Error> { Ok(self.0) } + + type Seed = (); + + fn from_seed(seed: Self::Seed) -> Self { + Self::default() + } } any_trait! { impl['a, 'ctx] JsonLike = [ dyn Value<'a, OwnedStatic<bool>> + 'a, dyn Sequence<'ctx> + 'a, - ]; + ] } impl Value<'_, OwnedStatic<bool>> for JsonLike { diff --git a/tests/hook.rs b/tests/hook.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/hook.rs |