| -rw-r--r-- | src/build.rs | 4 | ||||
| -rw-r--r-- | src/impls/core/bool.rs | 8 | ||||
| -rw-r--r-- | src/protocol.rs | 18 | ||||
| -rw-r--r-- | src/protocols.rs | 1 | ||||
| -rw-r--r-- | tests/demo.rs | 173 |
5 files changed, 179 insertions, 25 deletions
diff --git a/src/build.rs b/src/build.rs index 1c28354..b5dfc75 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,3 +1,5 @@ +use core::any::TypeId; + use crate::protocol::Implementer; /// A type buildable from a walker. @@ -18,4 +20,6 @@ pub trait Builder<'ctx>: Default { /// Finish the value. fn build(self) -> Result<Self::Value, Self::Error>; + + fn accepts(id: TypeId) -> bool; } diff --git a/src/impls/core/bool.rs b/src/impls/core/bool.rs index 2e3aba9..cdc1337 100644 --- a/src/impls/core/bool.rs +++ b/src/impls/core/bool.rs @@ -1,7 +1,9 @@ +use core::any::TypeId; + use crate::{ build::{Build, Builder}, implementer, - protocol::{ImplementerExt, Implementer}, + protocol::{Implementer, ImplementerExt}, protocols::{bool, ControlFlow}, walk::WalkOnce, }; @@ -32,6 +34,10 @@ impl<'ctx> Builder<'ctx> for BoolBuilder { None => Err(IncompleteValue), } } + + fn accepts(id: core::any::TypeId) -> bool { + id == TypeId::of::<bool::Bool>() + } } implementer! { diff --git a/src/protocol.rs b/src/protocol.rs index 2b48fc8..2535449 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -50,12 +50,26 @@ macro_rules! implementer { } } - $(impl<$ctx> $crate::protocol::Implementation<$ctx, $protocol> for $name { + $crate::implementer! { + $ctx $name [$($protocol),*] [$($generic)*] + } + }; + { + $ctx:lifetime $name:ty [$protocol:ty] [$($generic:tt)*] + } => { + impl<$ctx $($generic)*> $crate::protocol::Implementation<$ctx, $protocol> for $name { fn as_object(&mut self) -> <$protocol as $crate::protocol::Protocol>::Object<'_, $ctx> { self } + } + }; + { + $ctx:lifetime $name:ty [$($protocol:ty),*] $generic:tt + } => { + $($crate::implementer! { + $ctx $name [$protocol] $generic })* - } + }; } #[doc(inline)] pub use implementer; diff --git a/src/protocols.rs b/src/protocols.rs index 6e0ae5f..3f1d597 100644 --- a/src/protocols.rs +++ b/src/protocols.rs @@ -56,6 +56,7 @@ pub mod recoverable { pub mod sequence { use crate::protocol::{Implementer, Protocol}; + #[derive(PartialEq)] pub enum ControlFlow { Done, Continue, diff --git a/tests/demo.rs b/tests/demo.rs index 65b1083..900ba42 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -1,62 +1,191 @@ use std::any::TypeId; use uniserde::{ - Build, Builder, impls::core::iterator::IterWalker, - protocol::{implementer, AnyImpl, Implementation, Implementer}, + protocol::{implementer, AnyImpl, Implementation, Implementer, ImplementerExt}, protocols::{sequence, ControlFlow}, - transform, - WalkOnce, + transform, Build, Builder, WalkOnce, }; #[test] fn demo() { - let a = vec![true, false, true]; + let a = Data::Sequence(vec![ + Data::Bool(true), + Data::Sequence(vec![Data::Bool(false), Data::Bool(true)]), + Data::Bool(false), + ]); - let mut builder = ArrayBuilder::default(); - IterWalker::new(a).walk_once(builder.as_visitor()); + // let mut builder = <Data as Build>::Builder::default(); + let mut builder = StringBuilder::default(); + a.walk_once(builder.as_visitor()); dbg!(builder.build()); todo!() } -#[no_mangle] -fn example(a: [bool; 3]) -> [bool; 3] { - let mut builder = ArrayBuilder::default(); - let _ = IterWalker::new(a).walk_once(builder.as_visitor()); - builder.build().unwrap() +#[derive(Debug)] +enum Data { + Bool(bool), + Sequence(Vec<Data>), +} + +impl<'ctx> WalkOnce<'ctx> for Data { + type Error = (); + + type Value = (); + + fn walk_once(self, visitor: &mut dyn Implementer<'ctx>) -> Result<Self::Value, Self::Error> { + match self { + Data::Bool(value) => value.walk_once(visitor), + Data::Sequence(list) => IterWalker::new(list).walk_once(visitor), + } + } +} + +#[derive(Default)] +struct StringBuilder(String); + +impl<'ctx> Builder<'ctx> for StringBuilder { + type Error = (); + + type Value = String; + + fn as_visitor(&mut self) -> &mut dyn Implementer<'ctx> { + self + } + + fn build(self) -> Result<Self::Value, Self::Error> { + Ok(self.0) + } + + fn accepts(id: TypeId) -> bool { + id == TypeId::of::<uniserde::protocols::sequence::Sequence>() || + id == TypeId::of::<uniserde::protocols::bool::Bool>() + } +} + +implementer! { + impl['ctx] StringBuilder = [sequence::Sequence, uniserde::protocols::bool::Bool]; +} + +impl<'ctx> uniserde::protocols::sequence::Object<'ctx> for StringBuilder { + fn visit(&mut self, accessor: &mut dyn sequence::Accessor<'ctx>) -> uniserde::protocols::ControlFlow { + self.0.push('['); + loop { + if accessor.next(self) != uniserde::protocols::sequence::ControlFlow::Continue { + break + } + self.0.push_str(", "); + } + self.0.push(']'); + uniserde::protocols::ControlFlow::Done + } +} + +impl<'ctx> uniserde::protocols::bool::Object<'ctx> for StringBuilder { + fn visit(&mut self, value: bool) -> ControlFlow { + self.0.push_str(&value.to_string()); + ControlFlow::Done + } } #[derive(Default)] -struct ArrayBuilder([Option<bool>; 3]); +enum DataBuilder { + #[default] + Empty, + Bool(<bool as Build<'static>>::Builder), + Sequence(VecBuilder<Data>), +} + +impl<'ctx> Build<'ctx> for Data { + type Builder = DataBuilder; +} + +impl<'ctx> Builder<'ctx> for DataBuilder { + type Error = (); + + type Value = Data; + + fn as_visitor(&mut self) -> &mut dyn Implementer<'ctx> { + self + } + + fn build(self) -> Result<Self::Value, Self::Error> { + match self { + DataBuilder::Empty => Err(()), + DataBuilder::Bool(value) => Ok(Data::Bool(value.build().unwrap())), + DataBuilder::Sequence(list) => Ok(Data::Sequence(list.build().unwrap())), + } + } -impl<'ctx> Builder<'ctx> for ArrayBuilder { + fn accepts(id: TypeId) -> bool { + <<bool as Build>::Builder as Builder>::accepts(id) + || <VecBuilder<Data> as Builder>::accepts(id) + } +} + +impl<'ctx> Implementer<'ctx> for DataBuilder { + fn interface(&mut self, id: TypeId) -> Option<AnyImpl<'_, 'ctx>> { + if <<bool as Build>::Builder as Builder>::accepts(id) { + let builder = <<bool as Build>::Builder as Default>::default(); + *self = Self::Bool(builder); + } else if VecBuilder::<Data>::accepts(id) { + let builder = VecBuilder::<Data>::default(); + *self = Self::Sequence(builder); + } + + match self { + DataBuilder::Empty => panic!(), + DataBuilder::Bool(builder) => builder.interface(id), + DataBuilder::Sequence(builder) => builder.interface(id), + } + } +} + +struct VecBuilder<T>(Vec<T>); + +impl<T> Default for VecBuilder<T> { + fn default() -> Self { + Self(Vec::new()) + } +} + +impl<'ctx, T: Build<'ctx>> Builder<'ctx> for VecBuilder<T> { type Error = (); - type Value = [bool; 3]; + type Value = Vec<T>; fn as_visitor(&mut self) -> &mut dyn uniserde::protocol::Implementer<'ctx> { self } fn build(self) -> Result<Self::Value, Self::Error> { - Ok([self.0[0].unwrap(), self.0[1].unwrap(), self.0[2].unwrap()]) + Ok(self.0) + } + + fn accepts(id: TypeId) -> bool { + id == TypeId::of::<uniserde::protocols::sequence::Sequence>() } } implementer! { - impl['ctx] ArrayBuilder = [sequence::Sequence]; + impl['ctx, T: Build<'ctx>] VecBuilder<T> = [sequence::Sequence]; } -impl<'ctx> sequence::Object<'ctx> for ArrayBuilder { +impl<'ctx, T: Build<'ctx>> sequence::Object<'ctx> for VecBuilder<T> { fn visit( &mut self, accessor: &mut dyn sequence::Accessor<'ctx>, ) -> uniserde::protocols::ControlFlow { - for slot in &mut self.0 { - let mut builder = <bool as Build>::Builder::default(); - accessor.next(builder.as_visitor()); - *slot = Some(builder.build().unwrap()); + loop { + let mut builder = <T as Build>::Builder::default(); + let flow = accessor.next(builder.as_visitor()); + if flow == uniserde::protocols::sequence::ControlFlow::Done { + break; + } else { + let Ok(value) = builder.build() else { panic!() }; + self.0.push(value); + } } ControlFlow::Done } |