working integration test
Konnor Andrews 2024-02-11
parent 2b7c1df · commit 06eb47f
-rw-r--r--src/any.rs69
-rw-r--r--src/any/static_wrapper.rs25
-rw-r--r--src/build.rs4
-rw-r--r--src/lib.rs11
-rw-r--r--src/protocol/visitor.rs3
-rw-r--r--src/protocol/visitor/request_hint.rs4
-rw-r--r--src/protocol/visitor/sequence.rs37
-rw-r--r--src/protocol/visitor/value.rs56
-rw-r--r--src/protocol/walker/hint.rs15
-rw-r--r--src/walk.rs4
-rw-r--r--tests/demo.rs210
11 files changed, 196 insertions, 242 deletions
diff --git a/src/any.rs b/src/any.rs
index 94998f8..54cbee1 100644
--- a/src/any.rs
+++ b/src/any.rs
@@ -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.
///
diff --git a/src/lib.rs b/src/lib.rs
index e632612..fb044d8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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(())
}
}