working integration test
| -rw-r--r-- | src/any.rs | 69 | ||||
| -rw-r--r-- | src/any/static_wrapper.rs | 25 | ||||
| -rw-r--r-- | src/build.rs | 4 | ||||
| -rw-r--r-- | src/lib.rs | 11 | ||||
| -rw-r--r-- | src/protocol/visitor.rs | 3 | ||||
| -rw-r--r-- | src/protocol/visitor/request_hint.rs | 4 | ||||
| -rw-r--r-- | src/protocol/visitor/sequence.rs | 37 | ||||
| -rw-r--r-- | src/protocol/visitor/value.rs | 56 | ||||
| -rw-r--r-- | src/protocol/walker/hint.rs | 15 | ||||
| -rw-r--r-- | src/walk.rs | 4 | ||||
| -rw-r--r-- | tests/demo.rs | 210 |
11 files changed, 196 insertions, 242 deletions
@@ -8,14 +8,14 @@ //! result in a "double fat pointer"?!, and those don't exist. //! //! This module solves both problems. First, [`LtAny`] is a lifetime containing -//! counterpart to [`Any`][core::any::Any]. [`LtAny`] allows one lifetime which +//! counterpart to [`Any`][core::any::Any]. [`LtAny`] allows one lifetime which //! [`treaty`][crate] uses for the `'ctx` lifetime shared by walkers and visitors. //! Second, [`IndirectLtAny`] is able to type erase a pointer like type even //! if it's a `!Sized` type. This allows for type erasing borrows of trait objects //! like `&dyn Trait`. //! //! For a type to be compatible with this module it needs to implement [`TypeNameable`] -//! to give it a unique [`TypeId`][core::any::TypeId]. This can be done manually +//! to give it a unique [`TypeId`][core::any::TypeId]. This can be done manually //! without unsafe code. However, its recommended to use the provided [`nameable`] //! macro when possible. @@ -33,9 +33,9 @@ use alloc::boxed::Box; /// /// The `'a` lifetime is the lifetime `Self` must outlive. /// The `'lt` lifetime is some arbitrary lifetime `Self` can use in it's definition. -/// +/// /// The [`nameable`] allows implementing this trait and [`TypeName`] with minimal effort. -/// For types that are `'static` they can be wrapped by the included wrappers in +/// For types that are `'static` they can be wrapped by the included wrappers in /// the [`static_wrapper`] module. /// /// This trait is circular with [`TypeName`] on [`Self::Name`]. @@ -63,7 +63,7 @@ pub trait TypeName<'a, 'lt>: 'static { /// Implement [`TypeNameable`] and generate a unique name type. /// -/// ``` +/// ```text /// use treaty::any::{nameable, TypeNameable, TypeName}; /// /// pub struct MyType<T>(pub T); @@ -81,7 +81,7 @@ pub trait TypeName<'a, 'lt>: 'static { /// The first list of generics are what will be passed to the generics of `Name`. /// The second `impl` is for [`TypeName`] in `Name`. The type given after the `where` /// needs to match the type given in the first `impl`. However, in the second impl -/// the `T` is a generic for a name not the generic for the type. That's why +/// the `T` is a generic for a name not the generic for the type. That's why /// `T::Nameable` is used instead of `T`. #[doc(hidden)] #[macro_export] @@ -133,52 +133,52 @@ pub use nameable; nameable! { pub struct Name['a, 'lt, T]; - impl [T::Name] for &'lt T where { - T: TypeNameable<'a, 'lt> + ?Sized, T::Name: Sized, 'lt: 'a + impl [T::Name] for &'lt T where { + T: TypeNameable<'a, 'lt> + ?Sized, 'lt: 'a } - impl [T] where &'lt T::Nameable { - T: TypeName<'a, 'lt>, T::Nameable: 'lt, 'lt: 'a + impl [T] where &'lt T::Nameable { + T: TypeName<'a, 'lt> + ?Sized, T::Nameable: 'lt, 'lt: 'a } } nameable! { pub struct Name['a, 'lt, T]; - impl [T::Name] for &'lt mut T where { - T: TypeNameable<'a, 'lt> + ?Sized, T::Name: Sized, 'lt: 'a + impl [T::Name] for &'lt mut T where { + T: TypeNameable<'a, 'lt> + ?Sized, 'lt: 'a } - impl [T] where &'lt mut T::Nameable { - T: TypeName<'a, 'lt>, T::Nameable: 'lt, 'lt: 'a + impl [T] where &'lt mut T::Nameable { + T: TypeName<'a, 'lt> + ?Sized, T::Nameable: 'lt, 'lt: 'a } } nameable! { pub struct Name['a, 'lt, T]; - impl [T::Name] for *const T where { - T: TypeNameable<'a, 'lt> + ?Sized, T::Name: Sized + impl [T::Name] for *const T where { + T: TypeNameable<'a, 'lt> + ?Sized } - impl [T] where *const T::Nameable { - T: TypeName<'a, 'lt> + impl [T] where *const T::Nameable { + T: TypeName<'a, 'lt> + ?Sized } } nameable! { pub struct Name['a, 'lt, T]; - impl [T::Name] for *mut T where { - T: TypeNameable<'a, 'lt> + ?Sized, T::Name: Sized + impl [T::Name] for *mut T where { + T: TypeNameable<'a, 'lt> + ?Sized } - impl [T] where *mut T::Nameable { - T: TypeName<'a, 'lt> + impl [T] where *mut T::Nameable { + T: TypeName<'a, 'lt> + ?Sized } } #[cfg(feature = "alloc")] nameable! { pub struct Name['a, 'lt, T]; - impl [T::Name] for Box<T> where { - T: TypeNameable<'a, 'lt> + ?Sized, T::Name: Sized + impl [T::Name] for Box<T> where { + T: TypeNameable<'a, 'lt> + ?Sized } - impl [T] where Box<T::Nameable> { - T: TypeName<'a, 'lt> + impl [T] where Box<T::Nameable> { + T: TypeName<'a, 'lt> + ?Sized } } @@ -277,7 +277,7 @@ impl<'a, 'lt> dyn LtAny<'lt> + 'a { /// Dynamic trait lookup. /// -/// This trait allows looking up the trait object form of `self` for a +/// This trait allows looking up the trait object form of `self` for a /// given trait object `id`. This is similar to upcasting to the trait given /// by `id` if [`AnyTrait`] had every trait as a super bound. /// @@ -308,7 +308,7 @@ impl<'a, 'lt> dyn LtAny<'lt> + 'a { /// struct Name['a, 'ctx]; /// impl for dyn ToNum + 'a where { } /// } -/// +/// /// // An example struct. /// struct MyNum(i32); /// @@ -626,9 +626,8 @@ mod test { struct X<'a>(&'a mut i32); nameable! { - ['a, 'lt] - X<'lt> where {'lt: 'a} - X<'lt> where {'lt: 'a} + struct Name['a, 'lt]; + impl for X<'lt> where {'lt: 'a} } #[test] @@ -636,8 +635,8 @@ mod test { trait Z {} nameable! { - ['a, 'ctx] - dyn Z + 'a where {'ctx: 'a} + struct Name['a, 'ctx]; + impl for dyn Z + 'a where {'ctx: 'a} } struct X<T>(T); @@ -658,8 +657,8 @@ mod test { } nameable! { - ['a, 'ctx] - dyn Z + 'a where {'ctx: 'a} + struct Name['a, 'ctx]; + impl for dyn Z + 'a where {'ctx: 'a} } struct X(i32); diff --git a/src/any/static_wrapper.rs b/src/any/static_wrapper.rs index cd687ce..ce26fdd 100644 --- a/src/any/static_wrapper.rs +++ b/src/any/static_wrapper.rs @@ -7,8 +7,8 @@ pub struct OwnedStatic<T: ?Sized>(pub T); nameable! { pub struct Name['a, 'lt, T]; - impl [T] for OwnedStatic<T> where { T: 'static } - impl [T] where OwnedStatic<T> { T: 'static } + impl [T] for OwnedStatic<T> where { T: ?Sized + 'static } + impl [T] where OwnedStatic<T> { T: ?Sized + 'static } } /// Impl of [`TypeNameable`] for `'static` types that are borrowed (`&'lt T`). @@ -16,8 +16,8 @@ pub struct BorrowedStatic<'lt, T: ?Sized>(pub &'lt T); nameable! { pub struct Name['a, 'lt, T]; - impl [T] for BorrowedStatic<'lt, T> where { T: 'static, 'lt: 'a } - impl [T] where BorrowedStatic<'lt, T> { T: 'static, 'lt: 'a } + impl [T] for BorrowedStatic<'lt, T> where { T: ?Sized + 'static, 'lt: 'a } + impl [T] where BorrowedStatic<'lt, T> { T: ?Sized + 'static, 'lt: 'a } } /// Impl of [`TypeNameable`] for `'static` types that are temporarily borrowed (`&'a T`). @@ -25,8 +25,8 @@ pub struct TempBorrowedStatic<'a, T: ?Sized>(pub &'a T); nameable! { pub struct Name['a, 'lt, T]; - impl [T] for TempBorrowedStatic<'a, T> where { T: 'static } - impl [T] where TempBorrowedStatic<'a, T> { T: 'static } + impl [T] for TempBorrowedStatic<'a, T> where { T: ?Sized + 'static } + impl [T] where TempBorrowedStatic<'a, T> { T: ?Sized + 'static } } /// Impl of [`TypeNameable`] for `'static` types that are borrowed mutably (`&'lt mut T`). @@ -34,8 +34,8 @@ pub struct BorrowedMutStatic<'lt, T: ?Sized>(pub &'lt mut T); nameable! { pub struct Name['a, 'lt, T]; - impl [T] for BorrowedMutStatic<'lt, T> where { T: 'static, 'lt: 'a } - impl [T] where BorrowedMutStatic<'lt, T> { T: 'static, 'lt: 'a } + impl [T] for BorrowedMutStatic<'lt, T> where { T: ?Sized + 'static, 'lt: 'a } + impl [T] where BorrowedMutStatic<'lt, T> { T: ?Sized + 'static, 'lt: 'a } } /// Impl of [`TypeNameable`] for `'static` types that are temporarily borrowed mutably (`&'a mut T`). @@ -43,8 +43,8 @@ pub struct TempBorrowedMutStatic<'a, T: ?Sized>(pub &'a mut T); nameable! { pub struct Name['a, 'lt, T]; - impl [T] for TempBorrowedMutStatic<'a, T> where { T: 'static } - impl [T] where TempBorrowedMutStatic<'a, T> { T: 'static } + impl [T] for TempBorrowedMutStatic<'a, T> where { T: ?Sized + 'static } + impl [T] where TempBorrowedMutStatic<'a, T> { T: ?Sized + 'static } } /// Impl of [`TypeNameable`] for `'static` types that are in a [`Box`] (`Box<T>`). @@ -54,7 +54,6 @@ pub struct BoxedStatic<T: ?Sized>(pub Box<T>); #[cfg(feature = "alloc")] nameable! { pub struct Name['a, 'lt, T]; - impl [T] for BoxedStatic<T> where { T: 'static } - impl [T] where BoxedStatic<T> { T: 'static } + impl [T] for BoxedStatic<T> where { T: ?Sized + 'static } + impl [T] where BoxedStatic<T> { T: ?Sized + 'static } } - diff --git a/src/build.rs b/src/build.rs index 640cd5c..efadc25 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,7 +1,7 @@ // pub mod builders; // pub mod protocols; -use crate::protocol::Implementer; +use crate::protocol::Visitor; /// A buildable type. pub trait Build<'ctx>: Sized { @@ -32,7 +32,7 @@ pub trait Builder<'ctx>: Default { /// Get the builder as a visitor that a walker can use. /// /// This is expected to just be `self`. - fn as_visitor(&mut self) -> &mut dyn Implementer<'ctx>; + fn as_visitor(&mut self) -> Visitor<'_, 'ctx>; /// Finish the value. /// @@ -2,18 +2,17 @@ //! #![cfg_attr(all(not(test), not(feature = "std")), no_std)] - #![deny(elided_lifetimes_in_paths)] #[cfg(feature = "alloc")] extern crate alloc; pub mod any; -// mod build; +mod build; // pub mod builtins; -// pub mod protocol; +pub mod protocol; pub mod symbol; -// mod walk; +mod walk; // pub mod impls; // pub mod transform; @@ -24,8 +23,8 @@ pub mod symbol; // pub use walk::Walk; // pub use walk::Walker; -// pub use build::*; -// pub use walk::*; +pub use build::*; +pub use walk::*; #[macro_export] macro_rules! Build { diff --git a/src/protocol/visitor.rs b/src/protocol/visitor.rs index b85f512..cee7dd4 100644 --- a/src/protocol/visitor.rs +++ b/src/protocol/visitor.rs @@ -1,8 +1,9 @@ mod request_hint; -// pub mod sequence; +mod sequence; // pub mod tagged; mod value; // pub mod borrow; pub use request_hint::*; +pub use sequence::*; pub use value::*; diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index bd5b12d..179a68a 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -12,6 +12,6 @@ pub trait RequestHint<'ctx> { } nameable! { - pub ['a, 'ctx] - dyn RequestHint<'ctx> + 'a where {'ctx: 'a} + pub struct Name['a, 'ctx]; + impl for dyn RequestHint<'ctx> + 'a where {'ctx: 'a} } diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index b143c12..3cb8897 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -1,27 +1,26 @@ - use crate::{ - builtins::walker::hint::Meta, - protocol::{Implementer, Protocol}, + nameable, + protocol::{walker::HintMeta, ControlFlow, Visitor}, }; -pub enum Sequence {} - -#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] -pub enum Status { - Done, - Continue, +pub trait Sequence<'ctx> { + fn visit(&mut self, scope: &mut dyn SequenceScope<'ctx>) -> ControlFlow; } -pub trait SequenceWalker<'ctx> { - fn next(&mut self, visitor: &mut dyn Implementer<'ctx>) -> Result<Status, ()>; +nameable! { + pub struct Name['a, 'ctx]; + impl for dyn Sequence<'ctx> + 'a where { 'ctx: 'a } + impl where dyn Sequence<'ctx> + 'a { 'ctx: 'a } } -pub trait Object<'ctx> { - fn visit(&mut self, walker: &mut dyn SequenceWalker<'ctx>) -> Result<(), ()>; +pub trait SequenceScope<'ctx> { + fn next(&mut self, visitor: Visitor<'_, 'ctx>) -> ControlFlow<(), Status>; } -impl Protocol for Sequence { - type Object<'a, 'ctx: 'a> = &'a mut dyn Object<'ctx>; +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] +pub enum Status { + Done, + Continue, } #[derive(Default)] @@ -33,8 +32,10 @@ pub struct Hint { pub len: (usize, Option<usize>), } -impl Meta for Sequence { - type Known<'a, 'ctx: 'a> = Known; +impl<'ctx> HintMeta<'ctx> for dyn Sequence<'ctx> + '_ { + type Known<'a> = Known + where + 'ctx: 'a; - type Hint<'a, 'ctx: 'a> = Hint; + type Hint = Hint; } diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index 87dbd47..3cb8908 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -3,6 +3,7 @@ //! In some sense, this is the most basic protocol. use crate::{ + any::{TypeName, TypeNameable}, nameable, protocol::{walker::HintMeta, ControlFlow}, }; @@ -24,9 +25,9 @@ pub trait Value<T> { } nameable! { - pub ['a, 'ctx, T] - dyn Value<T> + 'a where {T: ?Sized} - dyn Value<T::Nameable> + 'a where {T: ?Sized} + pub struct Name['a, 'ctx, T]; + impl [T::Name] for dyn Value<T> + 'a where { T: TypeNameable<'a, 'ctx> + ?Sized } + impl [T] where dyn Value<T::Nameable> + 'a { T: TypeName<'a, 'ctx> + ?Sized } } // This enrolls the Value protocol into the walker hint system. @@ -39,7 +40,10 @@ impl<'ctx, T> HintMeta<'ctx> for dyn Value<T> + '_ { #[cfg(test)] mod test { use crate::{ - any::{AnyTrait, Borrowed, BorrowedMut, Owned}, + any::{ + static_wrapper::{BorrowedMutStatic, BorrowedStatic, OwnedStatic}, + AnyTrait, + }, any_trait, }; @@ -49,15 +53,15 @@ mod test { fn visit() { struct Visitor(Option<i32>); - impl Value<Owned<i32>> for Visitor { - fn visit(&mut self, Owned(value): Owned<i32>) -> ControlFlow<()> { + impl Value<OwnedStatic<i32>> for Visitor { + fn visit(&mut self, OwnedStatic(value): OwnedStatic<i32>) -> ControlFlow<()> { self.0 = Some(value); ControlFlow::Continue(()) } } - impl Value<Borrowed<'_, i32>> for Visitor { - fn visit(&mut self, Borrowed(value): Borrowed<'_, i32>) -> ControlFlow<()> { + impl Value<BorrowedStatic<'_, i32>> for Visitor { + fn visit(&mut self, BorrowedStatic(value): BorrowedStatic<'_, i32>) -> ControlFlow<()> { self.0 = Some(*value); ControlFlow::Continue(()) } @@ -65,25 +69,25 @@ mod test { any_trait! { impl['a, 'ctx] Visitor = [ - dyn Value<Owned<i32>>, - dyn Value<Borrowed<'ctx, i32>>, + dyn Value<OwnedStatic<i32>>, + dyn Value<BorrowedStatic<'ctx, i32>>, ]; } let mut v = Visitor(None); let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<Owned<i32>>>() + .upcast_mut::<dyn Value<OwnedStatic<i32>>>() .unwrap() - .visit(Owned(42)); + .visit(OwnedStatic(42)); assert_eq!(v.0, Some(42)); let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<Borrowed<'_, i32>>>() + .upcast_mut::<dyn Value<BorrowedStatic<'_, i32>>>() .unwrap() - .visit(Borrowed(&101)); + .visit(BorrowedStatic(&101)); assert_eq!(v.0, Some(101)); } @@ -92,8 +96,11 @@ mod test { fn visit_borrowed() { struct Visitor<'ctx>(Option<&'ctx mut String>); - impl<'ctx> Value<BorrowedMut<'ctx, String>> for Visitor<'ctx> { - fn visit(&mut self, BorrowedMut(value): BorrowedMut<'ctx, String>) -> ControlFlow<()> { + impl<'ctx> Value<BorrowedMutStatic<'ctx, String>> for Visitor<'ctx> { + fn visit( + &mut self, + BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, + ) -> ControlFlow<()> { self.0 = Some(value); ControlFlow::Continue(()) } @@ -101,7 +108,7 @@ mod test { any_trait! { impl['a, 'ctx] Visitor<'ctx> = [ - dyn Value<BorrowedMut<'ctx, String>> + 'a, + dyn Value<BorrowedMutStatic<'ctx, String>> + 'a, ]; } @@ -112,7 +119,7 @@ mod test { object .upcast_mut::<dyn Value<_>>() .unwrap() - .visit(BorrowedMut(&mut y)); + .visit(BorrowedMutStatic(&mut y)); v.0.unwrap().push_str("def"); assert_eq!(y, "abcdef"); @@ -122,8 +129,11 @@ mod test { fn visit_borrowed_unsized() { struct Visitor<'ctx>(Option<&'ctx str>); - impl<'ctx> Value<Borrowed<'ctx, str>> for Visitor<'ctx> { - fn visit(&mut self, Borrowed(value): Borrowed<'ctx, str>) -> ControlFlow<()> { + impl<'ctx> Value<BorrowedStatic<'ctx, str>> for Visitor<'ctx> { + fn visit( + &mut self, + BorrowedStatic(value): BorrowedStatic<'ctx, str>, + ) -> ControlFlow<()> { self.0 = Some(value); ControlFlow::Continue(()) } @@ -131,7 +141,7 @@ mod test { any_trait! { impl['a, 'ctx] Visitor<'ctx> = [ - dyn Value<Borrowed<'ctx, str>> + 'a, + dyn Value<BorrowedStatic<'ctx, str>> + 'a, ]; } @@ -140,9 +150,9 @@ mod test { let y = String::from("abc"); let object: &mut dyn AnyTrait<'_> = &mut v; object - .upcast_mut::<dyn Value<Borrowed<'_, str>>>() + .upcast_mut::<dyn Value<BorrowedStatic<'_, str>>>() .unwrap() - .visit(Borrowed(&y)); + .visit(BorrowedStatic(&y)); assert_eq!(v.0, Some("abc")); } diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index fdcc46a..c7d85d1 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -5,6 +5,7 @@ //! to the walker about what it is expecting. use crate::{ + any::{TypeName, TypeNameable}, nameable, protocol::{ControlFlow, Visitor}, }; @@ -37,9 +38,13 @@ pub trait Hint<'ctx, Protocol: HintMeta<'ctx>> { } nameable! { - pub ['a, 'ctx, Protocol] - dyn Hint<'ctx, Protocol> + 'a where {'ctx: 'a, Protocol: ?Sized} - dyn Hint<'ctx, Protocol::Nameable> + 'a where {'ctx: 'a, Protocol: ?Sized} + pub struct Name['a, 'ctx, Protocol]; + impl [Protocol::Name] for dyn Hint<'ctx, Protocol> + 'a where { + Protocol: TypeNameable<'a, 'ctx> + ?Sized, 'ctx: 'a + } + impl [Protocol] where dyn Hint<'ctx, Protocol::Nameable> + 'a { + Protocol: TypeName<'a, 'ctx> + ?Sized, 'ctx: 'a + } } #[cfg(test)] @@ -54,8 +59,8 @@ mod test { struct Y; nameable! { - ['a, 'ctx] - Y where {} + struct Name['a, 'ctx]; + impl for Y where {} } impl<'ctx, X> Hint<'ctx, Y> for X { diff --git a/src/walk.rs b/src/walk.rs index b24a9a3..9eda9d8 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,7 +1,7 @@ // pub mod protocols; // pub mod walkers; -use crate::protocol::Implementer; +use crate::protocol::Visitor; /// A type that can be walked. pub trait Walk<'ctx>: Sized { @@ -30,5 +30,5 @@ pub trait Walker<'ctx> { /// Walk the value. /// /// The walker should send data to the `visitor` as it walks the value. - fn walk(self, visitor: &mut dyn Implementer<'ctx>) -> Result<Self::Output, Self::Error>; + fn walk(self, visitor: Visitor<'_, 'ctx>) -> Result<Self::Output, Self::Error>; } diff --git a/tests/demo.rs b/tests/demo.rs index 6875f89..6f3565b 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -1,10 +1,11 @@ -use std::any::TypeId; - -use uniserde::{ - impls::core::iterator::IterWalker, - protocol::{implementer, AnyImpl, Implementation, Implementer, ImplementerExt}, - protocols::{sequence, ControlFlow}, - transform, Build, Builder, WalkOnce, +use std::{any::TypeId, collections::VecDeque, ops::ControlFlow}; +use treaty::{ + any::{any_trait, static_wrapper::OwnedStatic}, + protocol::{ + visitor::{Sequence, SequenceScope, Value}, + Visitor, + }, + Builder, Walk, Walker, }; #[test] @@ -15,10 +16,9 @@ fn demo() { Data::Bool(false), ]); - // let mut builder = <Data as Build>::Builder::default(); - let mut builder = StringBuilder::default(); - a.walk_once(builder.as_visitor()); - dbg!(builder.build()); + let mut builder = JsonLike::default(); + <Data as Walk>::Walker::from(a).walk(builder.as_visitor()).unwrap(); + dbg!(builder.build().unwrap()); todo!() } @@ -29,167 +29,107 @@ enum Data { Sequence(Vec<Data>), } -impl<'ctx> WalkOnce<'ctx> for Data { - type Error = (); - - type Value = (); +const _: () = { + struct Impl(Data); - 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), + impl From<Data> for Impl { + fn from(value: Data) -> Self { + Self(value) } } -} -#[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 + impl<'ctx> Walk<'ctx> for Data { + type Walker = Impl; } - 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>() - } -} + impl<'ctx> Walker<'ctx> for Impl { + type Error = (); -implementer! { - impl['ctx] StringBuilder = [sequence::Sequence, uniserde::protocols::bool::Bool]; -} + type Output = (); -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; + fn walk(self, visitor: Visitor<'_, 'ctx>) -> Result<Self::Output, Self::Error> { + match self.0 { + Data::Bool(value) => walk_bool(value, visitor), + Data::Sequence(value) => walk_vec(value, visitor), } - self.0.push_str(", "); + Ok(()) } - 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)] -enum DataBuilder { - #[default] - Empty, - Bool(<bool as Build<'static>>::Builder), - Sequence(VecBuilder<Data>), -} +}; -impl<'ctx> Build<'ctx> for Data { - type Builder = DataBuilder; +fn walk_bool(value: bool, visitor: Visitor<'_, '_>) { + visitor + .upcast_mut::<dyn Value<OwnedStatic<bool>>>() + .unwrap() + .visit(OwnedStatic(value)); } -impl<'ctx> Builder<'ctx> for DataBuilder { - type Error = (); - - type Value = Data; +fn walk_vec(value: Vec<Data>, visitor: Visitor<'_, '_>) { + struct Scope(VecDeque<Data>); - fn as_visitor(&mut self) -> &mut dyn Implementer<'ctx> { - self - } + impl<'ctx> SequenceScope<'ctx> for Scope { + fn next( + &mut self, + visitor: Visitor<'_, 'ctx>, + ) -> treaty::protocol::ControlFlow<(), treaty::protocol::visitor::Status> { + if let Some(value) = self.0.pop_front() { + <<Data as Walk>::Walker>::from(value).walk(visitor).unwrap(); - 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())), + ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) + } else { + ControlFlow::Continue(treaty::protocol::visitor::Status::Done) + } } } - 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); - } + let mut scope = Scope(value.into()); - match self { - DataBuilder::Empty => panic!(), - DataBuilder::Bool(builder) => builder.interface(id), - DataBuilder::Sequence(builder) => builder.interface(id), - } - } + visitor + .upcast_mut::<dyn Sequence<'_>>() + .unwrap() + .visit(&mut scope); } -struct VecBuilder<T>(Vec<T>); - -impl<T> Default for VecBuilder<T> { - fn default() -> Self { - Self(Vec::new()) - } -} +#[derive(Default)] +struct JsonLike(String); -impl<'ctx, T: Build<'ctx>> Builder<'ctx> for VecBuilder<T> { +impl<'ctx> Builder<'ctx> for JsonLike { type Error = (); - type Value = Vec<T>; + type Value = String; - fn as_visitor(&mut self) -> &mut dyn uniserde::protocol::Implementer<'ctx> { + fn as_visitor(&mut self) -> Visitor<'_, '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>() - } +any_trait! { + impl['a, 'ctx] JsonLike = [ + dyn Value<OwnedStatic<bool>> + 'a, + dyn Sequence<'ctx> + 'a, + ]; } -implementer! { - impl['ctx, T: Build<'ctx>] VecBuilder<T> = [sequence::Sequence]; +impl Value<OwnedStatic<bool>> for JsonLike { + fn visit(&mut self, value: OwnedStatic<bool>) -> treaty::protocol::ControlFlow { + self.0.push_str(&format!("{}", value.0)); + ControlFlow::Continue(()) + } } -impl<'ctx, T: Build<'ctx>> sequence::Object<'ctx> for VecBuilder<T> { - fn visit( - &mut self, - accessor: &mut dyn sequence::Accessor<'ctx>, - ) -> uniserde::protocols::ControlFlow { - 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); - } +impl<'ctx> Sequence<'ctx> for JsonLike { + fn visit(&mut self, scope: &mut dyn SequenceScope<'ctx>) -> treaty::protocol::ControlFlow { + self.0.push_str("["); + while let ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) = + scope.next(self) + { + self.0.push_str(","); } - ControlFlow::Done + self.0.push_str("]"); + ControlFlow::Continue(()) } } |