added serde deserialize builder
Konnor Andrews 2024-03-13
parent 75495bb · commit 0f5b2de
-rw-r--r--Cargo.lock24
-rw-r--r--Cargo.toml3
-rw-r--r--src/any.rs6
-rw-r--r--src/build.rs39
-rw-r--r--src/build/builders.rs3
-rw-r--r--src/build/builders/core/array.rs53
-rw-r--r--src/build/builders/core/bool.rs14
-rw-r--r--src/build/builders/serde.rs2
-rw-r--r--src/build/builders/serde/deserialize.rs142
-rw-r--r--src/build/builders/serde/deserialize_seed.rs167
-rw-r--r--src/walk/walkers/core/array.rs19
-rw-r--r--tests/demo.rs21
-rw-r--r--tests/hook.rs0
13 files changed, 438 insertions, 55 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 113b721..1b0bfc2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
]
diff --git a/Cargo.toml b/Cargo.toml
index 8972d74..09cb979 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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]
diff --git a/src/any.rs b/src/any.rs
index 453d0a4..b069043 100644
--- a/src/any.rs
+++ b/src/any.rs
@@ -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