| -rw-r--r-- | src/build.rs | 63 | ||||
| -rw-r--r-- | src/build/builders/core/array.rs | 33 | ||||
| -rw-r--r-- | src/build/builders/core/bool.rs | 28 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize.rs | 34 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize_seed.rs | 39 | ||||
| -rw-r--r-- | src/hkt.rs | 12 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/protocol.rs | 106 | ||||
| -rw-r--r-- | src/protocol/visitor/request_hint.rs | 10 | ||||
| -rw-r--r-- | src/protocol/visitor/sequence.rs | 28 | ||||
| -rw-r--r-- | src/protocol/visitor/tagged.rs | 28 | ||||
| -rw-r--r-- | src/protocol/visitor/value.rs | 42 | ||||
| -rw-r--r-- | src/protocol/walker/hint.rs | 25 | ||||
| -rw-r--r-- | src/walk.rs | 9 | ||||
| -rw-r--r-- | src/walk/walkers/core/array.rs | 19 | ||||
| -rw-r--r-- | src/walk/walkers/core/bool.rs | 11 | ||||
| -rw-r--r-- | tests/demo.rs | 70 | ||||
| -rw-r--r-- | tests/hook.rs | 40 |
18 files changed, 362 insertions, 237 deletions
diff --git a/src/build.rs b/src/build.rs index 72f395d..b75fa6b 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,12 +1,12 @@ pub mod builders; use crate::{ - protocol::{AnyTraitSendObj as _, Effect, SyncEffect, Visitor}, + protocol::{AsObj as _, Effect, EffectAnyTrait, SyncEffect, Visitor, Yield}, Walker, }; /// A buildable type. -pub trait Build<'ctx, E: Effect<'ctx>>: Sized { +pub trait Build<'ctx, E: EffectAnyTrait<'ctx>>: Sized { /// The builder that can be used to build a value of `Self`. type Builder: Builder<'ctx, E, Value = Self>; } @@ -24,7 +24,9 @@ pub trait Build<'ctx, E: Effect<'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, E: Effect<'ctx>>: AsVisitor<'ctx, E> { +pub trait Builder<'ctx, E: EffectAnyTrait<'ctx>>: AsVisitor<'ctx, E> { + type Effect: Effect<'ctx, Result<Self::Value, Self::Error>>; + type Seed; /// Error that can happen during filling the builder with data. @@ -39,21 +41,21 @@ pub trait Builder<'ctx, E: Effect<'ctx>>: AsVisitor<'ctx, E> { /// /// If an error happened with the builder during the walk /// it will be reported here. - fn build(self) -> Result<Self::Value, Self::Error>; + fn build<'a>(self) -> Yield<'a, 'ctx, Result<Self::Value, Self::Error>, Self::Effect> where Self: 'a; } -pub trait AsVisitor<'ctx, E: Effect<'ctx>> { +pub trait AsVisitor<'ctx, E: EffectAnyTrait<'ctx>> { /// Get the builder as a visitor that a walker can use. /// /// This is expected to just be `self`. fn as_visitor(&mut self) -> Visitor<'_, 'ctx, E>; } -pub trait DefaultBuilder<'ctx, E: Effect<'ctx>>: Builder<'ctx, E> { +pub trait DefaultBuilder<'ctx, E: EffectAnyTrait<'ctx>>: Builder<'ctx, E> { fn default() -> Self; } -impl<'ctx, B: Builder<'ctx, E>, E: Effect<'ctx>> DefaultBuilder<'ctx, E> for B +impl<'ctx, B: Builder<'ctx, E>, E: EffectAnyTrait<'ctx>> DefaultBuilder<'ctx, E> for B where B::Seed: Default, { @@ -68,29 +70,30 @@ pub enum BuildError<B, W> { Walker(W), } -// #[inline] -// pub fn build<'ctx, T: Build<'ctx, SyncEffect>, W: for<'a> Walker<'a, 'ctx, Effect = SyncEffect>>( -// walker: W, -// ) -> Result< -// T, -// BuildError< -// <<T as Build<'ctx, SyncEffect>>::Builder as Builder<'ctx, SyncEffect>>::Error, -// W::Error, -// >, -// > -// where -// <<T as Build<'ctx, SyncEffect>>::Builder as Builder<'ctx, SyncEffect>>::Seed: Default, -// { -// let mut builder = T::Builder::from_seed(Default::default()); -// -// if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor().as_obj_mut()) { -// return Err(BuildError::Walker(err)); -// } -// -// builder.build().map_err(BuildError::Builder) -// } +#[inline] +pub fn build<'ctx, T: Build<'ctx, SyncEffect>, W: Walker<'ctx, Effect = SyncEffect>>( + walker: W, +) -> Result< + T, + BuildError< + <<T as Build<'ctx, SyncEffect>>::Builder as Builder<'ctx, SyncEffect>>::Error, + W::Error, + >, +> +where + <T as Build<'ctx, SyncEffect>>::Builder: Builder<'ctx, SyncEffect, Effect = SyncEffect>, + <<T as Build<'ctx, SyncEffect>>::Builder as Builder<'ctx, SyncEffect>>::Seed: Default, +{ + let mut builder = T::Builder::from_seed(Default::default()); + + if let Err(err) = walker.walk(builder.as_visitor().as_obj_mut()) { + return Err(BuildError::Walker(err)); + } + + builder.build().map_err(BuildError::Builder) +} -pub fn build_with<'ctx, B: Builder<'ctx, SyncEffect>, W: Walker<'ctx, Effect = SyncEffect>>( +pub fn build_with<'ctx, B: Builder<'ctx, SyncEffect, Effect = SyncEffect>, W: Walker<'ctx, Effect = SyncEffect>>( walker: W, ) -> Result<B::Value, BuildError<B::Error, W::Error>> where @@ -98,7 +101,7 @@ where { let mut builder = B::from_seed(Default::default()); - if let core::ops::ControlFlow::Break(err) = walker.walk(builder.as_visitor().as_obj_mut()) { + if let Err(err) = walker.walk(builder.as_visitor().as_obj_mut()) { return Err(BuildError::Walker(err)); } diff --git a/src/build/builders/core/array.rs b/src/build/builders/core/array.rs index aca8775..34b8f65 100644 --- a/src/build/builders/core/array.rs +++ b/src/build/builders/core/array.rs @@ -4,7 +4,7 @@ use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status}, - AnyTraitObj, AnyTraitSendObj as _, ControlFlowFor, Effect, SyncEffect, + AsObj as _, Yield, Effect, SyncEffect, EffectAnyTrait, }, AsVisitor, DefaultBuilder, }; @@ -15,7 +15,7 @@ use crate::protocol::AsyncEffect; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -impl<'ctx, T, const N: usize, E: Effect<'ctx>> crate::Build<'ctx, E> for [T; N] +impl<'ctx, T, const N: usize, E: EffectAnyTrait<'ctx>> crate::Build<'ctx, E> for [T; N] where T: crate::Build<'ctx, E>, <T as crate::Build<'ctx, E>>::Builder: DefaultBuilder<'ctx, E>, @@ -30,15 +30,15 @@ pub enum ArrayError<E> { Item(usize, E), } -pub struct Builder<'ctx, B: crate::Builder<'ctx, E>, const N: usize, E: Effect<'ctx>> { +pub struct Builder<'ctx, B: crate::Builder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> { array: MaybeUninit<[B::Value; N]>, index: usize, item_err: Option<(usize, B::Error)>, _marker: PhantomData<fn() -> E>, } -impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'ctx>> crate::Builder<'ctx, E> - for Builder<'ctx, B, N, E> +impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> + crate::Builder<'ctx, E> for Builder<'ctx, B, N, E> where Self: AsVisitor<'ctx, E>, { @@ -46,7 +46,7 @@ where type Value = [B::Value; N]; - fn build(self) -> Result<Self::Value, Self::Error> { + fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { if let Some((index, err)) = self.item_err { return Err(ArrayError::Item(index, err)); } @@ -68,21 +68,25 @@ where _marker: PhantomData, } } + + type Effect = SyncEffect; } impl<'ctx, B: crate::DefaultBuilder<'ctx, SyncEffect>, const N: usize> AsVisitor<'ctx, SyncEffect> for Builder<'ctx, B, N, SyncEffect> +where + B: crate::Builder<'ctx, SyncEffect, Effect = SyncEffect> { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { - AnyTraitObj::from_obj(self) + self } } // #[cfg(not(feature = "alloc"))] any_trait! { - impl['a, 'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'ctx>] Builder<'ctx, B, N, E> = [ - dyn Sequence<'ctx> + 'a, - ] + impl['a, 'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'ctx, ControlFlow<(), ()>>] Builder<'ctx, B, N, E> = [ + dyn Sequence<'ctx, SyncEffect> + 'a, + ] where B: crate::Builder<'ctx, E, Effect = SyncEffect> } // #[cfg(feature = "alloc")] @@ -93,11 +97,16 @@ any_trait! { // ] // } -impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: Effect<'ctx>> Sequence<'ctx> +impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> Sequence<'ctx, SyncEffect> for Builder<'ctx, B, N, E> +where + B: crate::Builder<'ctx, E, Effect = SyncEffect> { #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a, 'ctx> where 'ctx: 'a { + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { loop { // Check if the array is full. if self.index >= N { diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs index 19fee66..c9c0be9 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -3,14 +3,11 @@ use core::{marker::PhantomData, ops::ControlFlow}; use crate::{ any::static_wrapper::OwnedStatic, any_trait, - protocol::{ - visitor::Value, AnyTraitObj, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, - SyncEffect, - }, + protocol::{visitor::Value, AsObj, AsyncEffect, Yield, Effect, SyncEffect}, AsVisitor, }; -impl<'ctx, E: Effect<'ctx>> crate::Build<'ctx, E> for bool +impl<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> crate::Build<'ctx, E> for bool where Builder<E>: AsVisitor<'ctx, E>, { @@ -24,7 +21,7 @@ pub enum Error { pub struct Builder<E>(Option<bool>, PhantomData<fn() -> E>); -impl<'ctx, E: Effect<'ctx>> crate::Builder<'ctx, E> for Builder<E> +impl<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> crate::Builder<'ctx, E> for Builder<E> where Self: AsVisitor<'ctx, E>, { @@ -33,38 +30,43 @@ where type Value = bool; #[inline] - fn build(self) -> Result<Self::Value, Self::Error> { + fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { self.0.ok_or(Error::Incomplete) } type Seed = (); - fn from_seed(seed: Self::Seed) -> Self { + fn from_seed(_seed: Self::Seed) -> Self { Self(None, PhantomData) } + + type Effect = SyncEffect; } impl<'ctx> AsVisitor<'ctx, SyncEffect> for Builder<SyncEffect> { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { - AnyTraitObj::from_obj(self) + self } } impl<'ctx> AsVisitor<'ctx, AsyncEffect> for Builder<AsyncEffect> { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { - AnyTraitSendObj::from_obj_send(self) + self } } any_trait! { impl['a, 'ctx, E] Builder<E> = [ - dyn Value<'ctx, OwnedStatic<bool>> + 'a, + dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, ] } -impl<'ctx, E> Value<'ctx, OwnedStatic<bool>> for Builder<E> { +impl<'ctx, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> for Builder<E> { #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx>where 'ctx: 'a { + fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { self.0 = Some(value); ControlFlow::Continue(()) } diff --git a/src/build/builders/serde/deserialize.rs b/src/build/builders/serde/deserialize.rs index 2fbc1c0..8a9fa3e 100644 --- a/src/build/builders/serde/deserialize.rs +++ b/src/build/builders/serde/deserialize.rs @@ -9,7 +9,7 @@ use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status, Value}, - AnyTraitObj, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, + AsObj, AsyncEffect, Yield, Effect, SyncEffect, }, AsVisitor, Builder as _, }; @@ -25,7 +25,7 @@ impl std::error::Error for Error {} pub struct Builder<T, E>(Result<T, Error>, PhantomData<fn() -> E>); -impl<'ctx, T: Deserialize<'ctx>, E: Effect<'ctx>> crate::Builder<'ctx, E> for Builder<T, E> +impl<'ctx, T: Deserialize<'ctx>, E: Effect<'ctx, ControlFlow<(), ()>>> crate::Builder<'ctx, E> for Builder<T, E> where Self: AsVisitor<'ctx, E>, { @@ -33,7 +33,7 @@ where type Value = T; - fn build(self) -> Result<Self::Value, Self::Error> { + fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { self.0 } @@ -42,35 +42,40 @@ where fn from_seed(seed: Self::Seed) -> Self { Self(Err(Error::Incomplete), PhantomData) } + + type Effect = SyncEffect; } impl<'ctx, T: Deserialize<'ctx>> AsVisitor<'ctx, SyncEffect> for Builder<T, SyncEffect> { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { - AnyTraitObj::from_obj(self) + self } } impl<'ctx, T: Deserialize<'ctx> + Send> AsVisitor<'ctx, AsyncEffect> for Builder<T, AsyncEffect> { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { - AnyTraitSendObj::from_obj_send(self) + self } } any_trait! { impl['a, 'ctx, T: Deserialize<'ctx>, E] Builder<T, E> = [ - dyn Value<'ctx, OwnedStatic<bool>> + 'a, - dyn Sequence<'ctx> + 'a, + dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Sequence<'ctx, SyncEffect> + 'a, ] } enum InjectedValue<'a, 'ctx> { Bool(bool), - Sequence(&'a mut dyn SequenceScope<'ctx>), + Sequence(&'a mut dyn SequenceScope<'ctx, SyncEffect>), } -impl<'ctx, T: Deserialize<'ctx>, E> Value<'ctx, OwnedStatic<bool>> for Builder<T, E> { +impl<'ctx, T: Deserialize<'ctx>, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> for Builder<T, E> { #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx> where 'ctx: 'a { + fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { self.0 = T::deserialize(InjectedValue::Bool(value)); if self.0.is_err() { @@ -81,9 +86,12 @@ impl<'ctx, T: Deserialize<'ctx>, E> Value<'ctx, OwnedStatic<bool>> for Builder<T } } -impl<'ctx, T: Deserialize<'ctx>, E> Sequence<'ctx> for Builder<T, E> { +impl<'ctx, T: Deserialize<'ctx>, E> Sequence<'ctx, SyncEffect> for Builder<T, E> { #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a, 'ctx> where 'ctx: 'a { + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { self.0 = T::deserialize(InjectedValue::Sequence(scope)); if self.0.is_err() { @@ -130,7 +138,7 @@ impl<'a, 'ctx> Deserializer<'ctx> for InjectedValue<'a, 'ctx> { } } -struct SequenceAccess<'a, 'ctx>(&'a mut dyn SequenceScope<'ctx>); +struct SequenceAccess<'a, 'ctx>(&'a mut dyn SequenceScope<'ctx, SyncEffect>); impl<'a, 'ctx> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx> { type Error = Error; diff --git a/src/build/builders/serde/deserialize_seed.rs b/src/build/builders/serde/deserialize_seed.rs index df38405..23434cf 100644 --- a/src/build/builders/serde/deserialize_seed.rs +++ b/src/build/builders/serde/deserialize_seed.rs @@ -12,7 +12,7 @@ use crate::{ any_trait, protocol::{ visitor::{Sequence, SequenceScope, Status, Value}, - AnyTraitObj, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, + AsObj, AsyncEffect, Yield, Effect, SyncEffect, }, AsVisitor, Builder as _, }; @@ -41,15 +41,17 @@ pub struct Builder<'ctx, T: DeserializeSeed<'ctx>, E>( PhantomData<fn() -> E>, ); -impl<'ctx, T: DeserializeSeed<'ctx>, E: Effect<'ctx>> crate::Builder<'ctx, E> for Builder<'ctx, T, E> +impl<'ctx, T: DeserializeSeed<'ctx>, E: Effect<'ctx, ControlFlow<(), ()>>> crate::Builder<'ctx, E> + for Builder<'ctx, T, E> where Self: AsVisitor<'ctx, E>, { + type Error = Error<T>; type Value = T::Value; - fn build(self) -> Result<Self::Value, Self::Error> { + fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { self.0 } @@ -58,11 +60,13 @@ where fn from_seed(seed: Self::Seed) -> Self { Self(Err(Error::Pending(seed)), PhantomData) } + + type Effect = SyncEffect; } impl<'ctx, T: DeserializeSeed<'ctx>> AsVisitor<'ctx, SyncEffect> for Builder<'ctx, T, SyncEffect> { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { - AnyTraitObj::from_obj(self) + self } } @@ -72,26 +76,32 @@ where T::Value: Send, { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { - AnyTraitSendObj::from_obj_send(self) + self } } any_trait! { impl['a, 'ctx, T: DeserializeSeed<'ctx>, E] Builder<'ctx, T, E> = [ - dyn Value<'ctx, OwnedStatic<bool>> + 'a, - dyn Sequence<'ctx> + 'a, + dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Sequence<'ctx, SyncEffect> + 'a, ] } enum InjectedValue<'a, 'ctx, T> { Bool(bool), - Sequence(&'a mut dyn SequenceScope<'ctx>), + Sequence(&'a mut dyn SequenceScope<'ctx, SyncEffect>), Extra(PhantomData<T>), } -impl<'ctx, T: DeserializeSeed<'ctx>, E> Value<'ctx, OwnedStatic<bool>> for Builder<'ctx, T, E> { +impl<'ctx, T: DeserializeSeed<'ctx>, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> for Builder<'ctx, T, E> { #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(bool_value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx> where 'ctx: 'a { + fn visit<'a>( + &'a mut self, + OwnedStatic(bool_value): OwnedStatic<bool>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); let Err(Error::Pending(value)) = pending else { todo!() @@ -107,9 +117,12 @@ impl<'ctx, T: DeserializeSeed<'ctx>, E> Value<'ctx, OwnedStatic<bool>> for Build } } -impl<'ctx, T: DeserializeSeed<'ctx>, E> Sequence<'ctx> for Builder<'ctx, T, E> { +impl<'ctx, T: DeserializeSeed<'ctx>, E> Sequence<'ctx, SyncEffect> for Builder<'ctx, T, E> { #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx>) -> ControlFlowFor<'a, 'ctx> where 'ctx: 'a { + fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); let Err(Error::Pending(value)) = pending else { todo!() @@ -162,7 +175,7 @@ impl<'a, 'ctx, T> Deserializer<'ctx> for InjectedValue<'a, 'ctx, T> { } } -struct SequenceAccess<'a, 'ctx, T>(&'a mut dyn SequenceScope<'ctx>, PhantomData<T>); +struct SequenceAccess<'a, 'ctx, T>(&'a mut dyn SequenceScope<'ctx, SyncEffect>, PhantomData<T>); impl<'a, 'ctx, T> SeqAccess<'ctx> for SequenceAccess<'a, 'ctx, T> { type Error = Error<T>; @@ -14,9 +14,9 @@ macro_rules! type_class { pub trait Hkt<$ctx>: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx>> {} - impl<$ctx, T> Hkt<$ctx> for T - where - T: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx>> + impl<$ctx, T> Hkt<$ctx> for T + where + T: for<$lt> ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx>> {} pub type T<$lt, $ctx, H> = <H as ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx>>>::T; @@ -32,14 +32,14 @@ pub use type_class; macro_rules! hkt { ( ($($type_class:tt)*): - for<$lt:lifetime, $ctx:lifetime> + for<$lt:lifetime, $ctx:lifetime> $vis:vis $name:ident$([$($generic:tt)*])? $(where {$($bound:tt)*})? => $($type:tt)* ) => { $vis struct $name<$ctx $(, $($generic)*)?>(core::marker::PhantomData<fn() -> (&$ctx (), $($($generic)*)?)>); - impl<$lt, $ctx $(, $($generic)*)?> $($type_class)*::ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx>> for $name<$ctx $(, $($generic)*)?> - $(where $($bound)*)? + impl<$lt, $ctx $(, $($generic)*)?> $($type_class)*::ForLt<$lt, $ctx, $crate::hkt::Bound<$lt, $ctx>> for $name<$ctx $(, $($generic)*)?> + $(where $($bound)*)? { type T = $($type)*; } @@ -9,9 +9,9 @@ extern crate alloc; pub mod any; mod build; +pub mod hkt; pub mod protocol; pub mod symbol; -pub mod hkt; mod walk; // pub mod impls; diff --git a/src/protocol.rs b/src/protocol.rs index 7ff6988..4ad6d8d 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -35,14 +35,14 @@ use core::{ future::Future, + marker::PhantomData, pin::{pin, Pin}, ptr, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, - marker::PhantomData, }; use crate::any::AnyTrait; -use crate::hkt::{type_class, hkt}; +use crate::hkt::{hkt, type_class}; pub mod visitor; pub mod walker; @@ -50,25 +50,18 @@ pub mod walker; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -pub type Visitor<'a, 'ctx, Effect> = any_trait_send_obj::T<'a, 'ctx, <Effect as self::Effect<'ctx>>::VisitorHkt>; -pub type Walker<'a, 'ctx, Effect> = any_trait_send_obj::T<'a, 'ctx, <Effect as self::Effect<'ctx>>::WalkerHkt>; - -pub trait AnyTraitObj<'a, 'ctx: 'a>: AnyTraitSendObj<'a, 'ctx> { - fn from_obj(value: &'a mut (dyn AnyTrait<'ctx> + 'a)) -> Self; -} +pub type Visitor<'a, 'ctx, Effect> = + as_obj::T<'a, 'ctx, <Effect as self::EffectAnyTrait<'ctx>>::AnyTrait>; +pub type Walker<'a, 'ctx, Effect> = + as_obj::T<'a, 'ctx, <Effect as self::EffectAnyTrait<'ctx>>::AnyTrait>; -pub trait AnyTraitSendObj<'a, 'ctx: 'a> { - fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self; +pub trait AsObj<'a, 'ctx: 'a> { fn as_obj(&self) -> &dyn AnyTrait<'ctx>; fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx>; fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx>; } -impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { - fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self { - value - } - +impl<'a, 'ctx: 'a> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { fn as_obj(&self) -> &dyn AnyTrait<'ctx> { *self } @@ -82,11 +75,7 @@ impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + ' } } -impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) { - fn from_obj_send(value: &'a mut (dyn AnyTrait<'ctx> + Send + 'a)) -> Self { - value - } - +impl<'a, 'ctx: 'a> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) { fn as_obj(&self) -> &dyn AnyTrait<'ctx> { *self } @@ -100,43 +89,65 @@ impl<'a, 'ctx: 'a> AnyTraitSendObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + S } } -impl<'a, 'ctx: 'a> AnyTraitObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { - fn from_obj(value: &'a mut (dyn AnyTrait<'ctx> + 'a)) -> Self { - value - } -} - -type_class!(for<'lt, 'ctx> pub any_trait_send_obj: AnyTraitSendObj<'lt, 'ctx>); +type_class!(for<'lt, 'ctx> pub as_obj: AsObj<'lt, 'ctx>); type_class!(for<'lt, 'ctx> pub any_t); -pub trait Effect<'ctx, C = (), B = ()>: 'static { - type VisitorHkt: any_trait_send_obj::Hkt<'ctx>; - type WalkerHkt: any_trait_send_obj::Hkt<'ctx>; - type ControlFlowHkt: any_t::Hkt<'ctx>; +pub trait EffectAnyTrait<'ctx>: 'static { + /// The `dyn AnyTrait<'ctx>` for the effect. + /// + /// this allows adding extra bounds to the trait object. + type AnyTrait: as_obj::Hkt<'ctx>; } -pub type ControlFlowFor<'a, 'ctx, E = SyncEffect, C = (), B = ()> = - any_t::T<'a, 'ctx, <E as Effect<'ctx, C, B>>::ControlFlowHkt>; +/// Trait for effects. +pub trait Effect<'ctx, T>: EffectAnyTrait<'ctx> { + /// The type functions return for this effect. + /// + /// This type should resolve into a `T`. + type Yield: any_t::Hkt<'ctx>; +} + +pub type Yield<'a, 'ctx, T, E> = any_t::T<'a, 'ctx, <E as Effect<'ctx, T>>::Yield>; pub enum SyncEffect {} -hkt!((any_trait_send_obj): for<'a, 'ctx> pub AnyTraitSendObjHkt => &'a mut (dyn AnyTrait<'ctx> + Send + 'a)); -hkt!((any_trait_send_obj): for<'a, 'ctx> pub AnyTraitObjHkt => &'a mut (dyn AnyTrait<'ctx> + 'a)); +hkt!((as_obj): for<'a, 'ctx> pub AnyTraitSendObj => &'a mut (dyn AnyTrait<'ctx> + Send + 'a)); +hkt!((as_obj): for<'a, 'ctx> pub AnyTraitObj => &'a mut (dyn AnyTrait<'ctx> + 'a)); -hkt!((any_t): for<'a, 'ctx> pub SyncControlFlowHkt[C, B] => core::ops::ControlFlow<B, C>); +hkt!((any_t): for<'a, 'ctx> pub SyncYield[T] => T); -impl<'ctx, C, B> Effect<'ctx, C, B> for SyncEffect { - type ControlFlowHkt = SyncControlFlowHkt<'ctx, C, B>; +impl<'ctx, T> Effect<'ctx, T> for SyncEffect { + type Yield = SyncYield<'ctx, T>; +} - type VisitorHkt = AnyTraitObjHkt<'ctx>; +impl<'ctx> EffectAnyTrait<'ctx> for SyncEffect { + type AnyTrait = AnyTraitObj<'ctx>; +} - type WalkerHkt = AnyTraitObjHkt<'ctx>; +#[cfg(feature = "alloc")] +hkt!((any_t): for<'a, 'ctx> pub AsyncSendYield[T] => + core::pin::Pin< + Box<dyn core::future::Future<Output = T> + Send + 'a>, + > +); + +#[cfg(feature = "alloc")] +pub enum AsyncSendEffect {} + +#[cfg(feature = "alloc")] +impl<'ctx, T> Effect<'ctx, T> for AsyncSendEffect { + type Yield = AsyncSendYield<'ctx, T>; +} + +#[cfg(feature = "alloc")] +impl<'ctx> EffectAnyTrait<'ctx> for AsyncSendEffect { + type AnyTrait = AnyTraitSendObj<'ctx>; } #[cfg(feature = "alloc")] -hkt!((any_t): for<'a, 'ctx> pub AsyncControlFlowHkt[C, B] => +hkt!((any_t): for<'a, 'ctx> pub AsyncYield[T] => core::pin::Pin< - Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + Send + 'a>, + Box<dyn core::future::Future<Output = T> + 'a>, > ); @@ -144,8 +155,11 @@ hkt!((any_t): for<'a, 'ctx> pub AsyncControlFlowHkt[C, B] => pub enum AsyncEffect {} #[cfg(feature = "alloc")] -impl<'ctx, C, B> Effect<'ctx, C, B> for AsyncEffect { - type VisitorHkt = AnyTraitSendObjHkt<'ctx>; - type WalkerHkt = AnyTraitSendObjHkt<'ctx>; - type ControlFlowHkt = AsyncControlFlowHkt<'ctx, C, B>; +impl<'ctx, T> Effect<'ctx, T> for AsyncEffect { + type Yield = AsyncYield<'ctx, T>; +} + +#[cfg(feature = "alloc")] +impl<'ctx> EffectAnyTrait<'ctx> for AsyncEffect { + type AnyTrait = AnyTraitObj<'ctx>; } diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index bf0ba98..d79ef73 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -1,21 +1,23 @@ +use core::ops::ControlFlow; + use crate::{ nameable, - protocol::{ControlFlowFor, Effect, SyncEffect, Walker}, + protocol::{Yield, Effect, SyncEffect, Walker}, }; /// Protocol for requesting a hint from a visitor. -pub trait RequestHint<'a, 'ctx: 'a, E: Effect<'ctx> = SyncEffect> { +pub trait RequestHint<'a, 'ctx: 'a, E: Effect<'ctx, ControlFlow<(), ()>>> { /// Call this to request a hint. /// /// `walker` is what the visitor (`self`) will call to give a hint using the /// [`Hint`][crate::builtins::walker::Hint] protocol. - fn request_hint(&'a mut self, walker: Walker<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E>; + fn request_hint(&'a mut self, walker: Walker<'a, 'ctx, E>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>; } nameable! { pub struct Name['a, 'ctx, E]; impl [E] for dyn RequestHint<'a, 'ctx, E> + 'a where { - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a } } diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index 47ea03e..d345ed1 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -1,35 +1,41 @@ +use core::ops::ControlFlow; + use crate::{ + hkt::hkt, nameable, - protocol::{walker::HintMeta, ControlFlowFor, Effect, SyncEffect, Visitor, any_t}, - hkt::hkt + protocol::{any_t, walker::HintMeta, Yield, Effect, SyncEffect, Visitor}, }; -pub trait Sequence<'ctx, E: Effect<'ctx> = SyncEffect> { +pub trait Sequence<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> { fn visit<'a>( &'a mut self, scope: &'a mut dyn SequenceScope<'ctx, E>, - ) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a; + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + where + 'ctx: 'a; } nameable! { pub struct Name['a, 'ctx, E]; impl [E] for dyn Sequence<'ctx, E> + 'a where { - E: Effect<'ctx> + Effect<'ctx, Status>, + E: Effect<'ctx, ControlFlow<(), ()>> + Effect<'ctx, ControlFlow<(), Status>>, 'ctx: 'a } impl [E] where dyn Sequence<'ctx, E> + 'a { - E: Effect<'ctx> + Effect<'ctx, Status>, + E: Effect<'ctx, ControlFlow<(), ()>> + Effect<'ctx, ControlFlow<(), Status>>, 'ctx: 'a } } -pub trait SequenceScope<'ctx, E = SyncEffect> +pub trait SequenceScope<'ctx, E> where - E: Effect<'ctx> + Effect<'ctx, Status>, + E: Effect<'ctx, ControlFlow<(), Status>>, { - fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E, Status> where 'ctx: 'a; + fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> Yield<'a, 'ctx, ControlFlow<(), Status>, E> + where + 'ctx: 'a; } #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] @@ -49,8 +55,8 @@ pub struct Hint { pub len: (usize, Option<usize>), } -impl<'a, 'ctx: 'a, E: Effect<'ctx>> HintMeta<'ctx> for dyn Sequence<'ctx, E> + '_ { - type KnownHkt = KnownHkt<'ctx>; +impl<'a, 'ctx: 'a, E: Effect<'ctx, ControlFlow<(), ()>>> HintMeta<'ctx> for dyn Sequence<'ctx, E> + '_ { + type Known = KnownHkt<'ctx>; type Hint = Hint; } diff --git a/src/protocol/visitor/tagged.rs b/src/protocol/visitor/tagged.rs index 1f33ca7..0bc90a0 100644 --- a/src/protocol/visitor/tagged.rs +++ b/src/protocol/visitor/tagged.rs @@ -1,37 +1,45 @@ +use core::ops::ControlFlow; + use crate::{ + hkt::hkt, nameable, - protocol::{walker::HintMeta, ControlFlowFor, Effect, SyncEffect, Visitor, any_t}, + protocol::{any_t, walker::HintMeta, Yield, Effect, SyncEffect, Visitor}, symbol::Symbol, - hkt::hkt, }; -pub trait Tagged<'ctx, E: Effect<'ctx> = SyncEffect> { +pub trait Tagged<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> { fn visit<'a>( &'a mut self, scope: &'a mut dyn TaggedScope<'ctx, E>, - ) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a; + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + where + 'ctx: 'a; } nameable! { pub struct Name['a, 'ctx, E]; impl [E] for dyn Tagged<'ctx, E> + 'a where { - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a } impl [E] where dyn Tagged<'ctx, E> + 'a { - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a } } -pub trait TaggedScope<'ctx, E: Effect<'ctx> = SyncEffect> { +pub trait TaggedScope<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> { fn kind(&mut self) -> Symbol; - fn tag<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a; + fn tag<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + where + 'ctx: 'a; - fn value<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a; + fn value<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + where + 'ctx: 'a; } hkt!((any_t): for<'a, 'ctx> pub KnownHkt => Known); @@ -45,7 +53,7 @@ pub struct Hint { } impl<'a, 'ctx: 'a, Return> HintMeta<'ctx> for dyn Tagged<'ctx, Return> + 'a { - type KnownHkt = KnownHkt<'ctx>; + type Known = KnownHkt<'ctx>; type Hint = Hint; } diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index 20438bb..ed3a0bd 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -2,17 +2,19 @@ //! //! In some sense, this is the most basic protocol. +use core::ops::ControlFlow; + use crate::{ any::{TypeName, TypeNameable}, - nameable, - protocol::{walker::HintMeta, ControlFlowFor, Effect, SyncEffect, any_t}, hkt::hkt, + nameable, + protocol::{any_t, walker::HintMeta, Effect, SyncEffect, Yield}, }; /// Trait object for the [`Value`] protocol. /// /// Types implementing the [`Value`] protocol will implement this trait. -pub trait Value<'ctx, T, E: Effect<'ctx> = SyncEffect> { +pub trait Value<'ctx, T, E: Effect<'ctx, ControlFlow<(), ()>>> { /// Visit a value of type `T`. /// /// Use this to give a value to a visitor. Its expected that a walker @@ -22,7 +24,9 @@ pub trait Value<'ctx, T, E: Effect<'ctx> = SyncEffect> { /// If a [`ControlFlow::Break`] is returned then the walker /// should stop walking as soon as possible as there has likely been /// and error. - fn visit<'a>(&'a mut self, value: T) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a; + fn visit<'a>(&'a mut self, value: T) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + where + 'ctx: 'a; } nameable! { @@ -30,13 +34,13 @@ nameable! { impl [T::Name, E] for dyn Value<'ctx, T, E> + 'a where { T: TypeNameable<'a, 'ctx> + ?Sized, - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a, } impl [T, E] where dyn Value<'ctx, T::Nameable, E> + 'a { T: TypeName<'a, 'ctx> + ?Sized, - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a, } } @@ -44,8 +48,10 @@ nameable! { hkt!((any_t): for<'a, 'ctx> pub KnownHkt => ()); // This enrolls the Value protocol into the walker hint system. -impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for dyn Value<'ctx, T, E> + 'a { - type KnownHkt = KnownHkt<'ctx>; +impl<'a, 'ctx: 'a, T, E: Effect<'ctx, ControlFlow<(), ()>>> HintMeta<'ctx> + for dyn Value<'ctx, T, E> + 'a +{ + type Known = KnownHkt<'ctx>; type Hint = (); } @@ -72,7 +78,10 @@ mod test { fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<i32>, - ) -> core::ops::ControlFlow<()> where 'ctx: 'a { + ) -> core::ops::ControlFlow<()> + where + 'ctx: 'a, + { self.0 = Some(value); ControlFlow::Continue(()) } @@ -82,7 +91,10 @@ mod test { fn visit<'a>( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, i32>, - ) -> core::ops::ControlFlow<()> where 'ctx: 'a { + ) -> core::ops::ControlFlow<()> + where + 'ctx: 'a, + { self.0 = Some(*value); ControlFlow::Continue(()) } @@ -121,7 +133,10 @@ mod test { fn visit<'a>( &'a mut self, BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, - ) -> ControlFlow<()> where 'ctx: 'a { + ) -> ControlFlow<()> + where + 'ctx: 'a, + { self.0 = Some(value); ControlFlow::Continue(()) } @@ -154,7 +169,10 @@ mod test { fn visit<'a>( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, str>, - ) -> ControlFlow<()> where 'ctx: 'a { + ) -> ControlFlow<()> + where + 'ctx: 'a, + { self.0 = Some(value); ControlFlow::Continue(()) } diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index ce73b7e..56d5793 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -4,10 +4,12 @@ //! this module gives a protocol by which a visitor can give a hint //! to the walker about what it is expecting. +use core::ops::ControlFlow; + use crate::{ any::{TypeName, TypeNameable}, nameable, - protocol::{ControlFlowFor, Effect, SyncEffect, Visitor, any_t}, + protocol::{any_t, Effect, EffectAnyTrait, SyncEffect, Visitor, Yield}, }; /// Meta information for the hint. @@ -18,16 +20,19 @@ pub trait HintMeta<'ctx> { /// /// This should be information easy to get without changing the state of the walker /// in an irreversible way. - type KnownHkt: any_t::Hkt<'ctx>; + type Known: any_t::Hkt<'ctx>; /// Extra information the visitor can give to the walker about what it is expecting. type Hint; } +pub type Known<'a, 'ctx, Protocol> = any_t::T<'a, 'ctx, <Protocol as HintMeta<'ctx>>::Known>; + /// Object implementing the [`Hint`] protocol. -pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E = SyncEffect> +pub trait Hint<'ctx, Protocol: ?Sized + HintMeta<'ctx>, E> where - E: Effect<'ctx> + for<'a> Effect<'ctx, <<Protocol as HintMeta<'ctx>>::KnownHkt as any_t::ForLt<'a, 'ctx, crate::hkt::Bound<'a, 'ctx>>>::T> + for<'a> E: Effect<'ctx, ControlFlow<(), ()>> + + Effect<'ctx, ControlFlow<(), Known<'a, 'ctx, Protocol>>>, { /// Hint to the walker to use the `P` protocol. /// @@ -36,13 +41,13 @@ where &'a mut self, visitor: Visitor<'a, 'ctx, E>, hint: <Protocol as HintMeta<'ctx>>::Hint, - ) -> ControlFlowFor<'a, 'ctx, E>; + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>; /// Ask the walker for information about it's support of the protocol. fn known<'a>( &'a mut self, hint: &'a <Protocol as HintMeta<'ctx>>::Hint, - ) -> ControlFlowFor<'a, 'ctx, E, any_t::T<'a, 'ctx, <Protocol as HintMeta<'ctx>>::KnownHkt>> + ) -> Yield<'a, 'ctx, ControlFlow<(), Known<'a, 'ctx, Protocol>>, E> where 'ctx: 'a; } @@ -52,13 +57,13 @@ nameable! { impl [Protocol::Name, E] for dyn Hint<'ctx, Protocol, E> + 'a where { Protocol: TypeNameable<'a, 'ctx> + ?Sized, - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a, } impl [Protocol, E] where dyn Hint<'ctx, Protocol::Nameable, E> + 'a { Protocol: TypeName<'a, 'ctx> + ?Sized, - E: Effect<'ctx>, + E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a, } } @@ -94,7 +99,7 @@ mod test { fn known<'a>( &'a mut self, hint: &'a <Y as HintMeta<'ctx>>::Hint, - ) -> ControlFlow<(), any_t::T<'a, 'ctx, <Y as HintMeta<'ctx>>::KnownHkt>> + ) -> ControlFlow<(), Known<'a, 'ctx, SyncEffect>> where 'ctx: 'a, { @@ -105,7 +110,7 @@ mod test { hkt!((any_t): for<'a, 'ctx> KnownHkt => ()); impl<'ctx> HintMeta<'ctx> for Y { - type KnownHkt = KnownHkt<'ctx>; + type Known = KnownHkt<'ctx>; type Hint = (); } diff --git a/src/walk.rs b/src/walk.rs index fa8ec4b..384760a 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,6 +1,6 @@ pub mod walkers; -use crate::protocol::{ControlFlowFor, Effect, Visitor}; +use crate::protocol::{Effect, EffectAnyTrait, Visitor, Yield}; /// A type that can be walked. pub trait Walk<'ctx>: Sized { @@ -22,7 +22,7 @@ pub fn into_walker<'ctx, T: Walk<'ctx>>(value: T) -> T::Walker { /// - Call [Self::walk()] to walk the value. Data will be sent to the provided /// visitor. pub trait Walker<'ctx> { - type Effect: Effect<'ctx, Self::Output, Self::Error> + Effect<'ctx>; + type Effect: Effect<'ctx, Result<Self::Output, Self::Error>>; type Error; @@ -38,5 +38,8 @@ pub trait Walker<'ctx> { fn walk<'a>( self, visitor: Visitor<'a, 'ctx, Self::Effect>, - ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> where Self: 'a, 'ctx: 'a; + ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect> + where + Self: 'a, + 'ctx: 'a; } diff --git a/src/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs index 33322db..4154e50 100644 --- a/src/walk/walkers/core/array.rs +++ b/src/walk/walkers/core/array.rs @@ -6,7 +6,7 @@ use crate::{ protocol::{ visitor::{RequestHint, Sequence, SequenceScope, Status}, walker::{Hint, HintMeta}, - ControlFlowFor, SyncEffect, Visitor, + Yield, SyncEffect, Visitor, }, }; @@ -54,7 +54,7 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From fn walk<'a>( mut self, visitor: Visitor<'a, 'ctx, Self::Effect>, - ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> + ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect> where Self: 'a, { @@ -63,21 +63,24 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From } if let Some((index, error)) = self.item_err { - ControlFlow::Break(WalkerError { index, error }) + Err(WalkerError { index, error }) } else { - ControlFlow::Continue(()) + Ok(()) } } } impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From<T>> - SequenceScope<'ctx> for Walker<'ctx, T, N, W> + SequenceScope<'ctx, SyncEffect> for Walker<'ctx, T, N, W> { #[inline] fn next<'a>( &'a mut self, visitor: Visitor<'a, 'ctx, SyncEffect>, - ) -> ControlFlowFor<'a, 'ctx, W::Effect, Status> where 'ctx: 'a { + ) -> Yield<'a, 'ctx, ControlFlow<(), Status>, W::Effect> + where + 'ctx: 'a, + { if self.index >= N { return ControlFlow::Continue(Status::Done); } @@ -93,8 +96,8 @@ impl<'ctx, T, const N: usize, W: crate::Walker<'ctx, Effect = SyncEffect> + From let walker = W::from(value); match walker.walk(visitor) { - ControlFlow::Continue(_) => ControlFlow::Continue(Status::Continue), - ControlFlow::Break(err) => { + Ok(_) => ControlFlow::Continue(Status::Continue), + Err(err) => { self.item_err = Some((self.index, err)); ControlFlow::Continue(Status::Done) } diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs index 34707d1..c51861a 100644 --- a/src/walk/walkers/core/bool.rs +++ b/src/walk/walkers/core/bool.rs @@ -9,7 +9,7 @@ use crate::{ protocol::{ visitor::{RequestHint, Sequence, SequenceScope, Status}, walker::{Hint, HintMeta}, - ControlFlowFor, SyncEffect, Visitor, + Yield, SyncEffect, Visitor, }, }; @@ -36,13 +36,16 @@ impl<'ctx> crate::Walker<'ctx> for Walker { fn walk<'a>( self, visitor: Visitor<'a, 'ctx, SyncEffect>, - ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> where 'ctx: 'a { + ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect> + where + 'ctx: 'a, + { { - if let Some(object) = visitor.upcast_mut::<dyn Value<'_, OwnedStatic<bool>> + '_>() { + if let Some(object) = visitor.upcast_mut::<dyn Value<'_, OwnedStatic<bool>, SyncEffect> + '_>() { object.visit(OwnedStatic(self.0)); } - ControlFlow::Continue(()) + Ok(()) } } } diff --git a/tests/demo.rs b/tests/demo.rs index 9812ef6..c644f73 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -6,9 +6,9 @@ use treaty::{ into_walker, protocol::{ visitor::{Sequence, SequenceScope, Value}, - ControlFlowFor, SyncEffect, Visitor, + Yield, SyncEffect, Visitor, }, - Builder, Walk, Walker, + AsVisitor, Builder, Walk, Walker, }; #[test] @@ -22,12 +22,12 @@ fn demo() { dbg!(array_to_array2([true, false])); dbg!(array_to_array([true, true])); - let s = build_with::<array::Builder<'_, JsonLike, 3>, _>(into_walker(&a)).unwrap(); + 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(); + let x = build_with::<SerdeBuilder<serde_json::Value, _>, _>(into_walker(&a)).unwrap(); dbg!(x); // let s = build_with::<JsonLike, _>(into_walker(a)).unwrap(); @@ -74,32 +74,38 @@ const _: () = { fn walk<'a>( self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, SyncEffect, Self::Error, Self::Output> { + visitor: Visitor<'a, 'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, SyncEffect> + where + 'ctx: 'a, + { match self.0 { Data::Bool(value) => walk_bool(*value, visitor), Data::Sequence(value) => walk_vec(value, visitor), } - core::ops::ControlFlow::Continue(()) + Ok(()) } } }; -fn walk_bool(value: bool, visitor: &mut Visitor<'_, '_>) { +fn walk_bool(value: bool, visitor: Visitor<'_, '_, SyncEffect>) { visitor - .upcast_mut::<dyn Value<OwnedStatic<bool>>>() + .upcast_mut::<dyn Value<OwnedStatic<bool>, SyncEffect>>() .unwrap() .visit(OwnedStatic(value)); } -fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: &'a mut Visitor<'a, 'ctx>) { +fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: Visitor<'a, 'ctx, SyncEffect>) { struct Scope<'ctx>(VecDeque<&'ctx Data>); - impl<'ctx> SequenceScope<'ctx> for Scope<'ctx> { + impl<'ctx> SequenceScope<'ctx, SyncEffect> for Scope<'ctx> { fn next<'a>( &'a mut self, - visitor: &'a mut Visitor<'a, 'ctx>, - ) -> ControlFlowFor<'a, SyncEffect, treaty::protocol::visitor::Status> { + visitor: Visitor<'a, 'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), treaty::protocol::visitor::Status>, SyncEffect> + where + 'ctx: 'a, + { if let Some(value) = self.0.pop_front() { into_walker(value).walk(visitor); @@ -113,7 +119,7 @@ fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: &'a mut Visitor<'a, 'ctx>) { let mut scope = Scope(value.into_iter().collect()); visitor - .upcast_mut::<dyn Sequence<'_>>() + .upcast_mut::<dyn Sequence<'_, SyncEffect>>() .unwrap() .visit(&mut scope); } @@ -121,16 +127,12 @@ fn walk_vec<'a, 'ctx>(value: &'ctx [Data], visitor: &'a mut Visitor<'a, 'ctx>) { #[derive(Default)] struct JsonLike(String); -impl<'ctx> Builder<'ctx> for JsonLike { +impl<'ctx> Builder<'ctx, SyncEffect> for JsonLike { type Error = (); type Value = String; - fn as_visitor(&mut self) -> &mut Visitor<'_, 'ctx> { - self - } - - fn build(self) -> Result<Self::Value, Self::Error> { + fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { Ok(self.0) } @@ -139,27 +141,41 @@ impl<'ctx> Builder<'ctx> for JsonLike { fn from_seed(seed: Self::Seed) -> Self { Self::default() } + + type Effect = SyncEffect; +} + +impl<'ctx> AsVisitor<'ctx, SyncEffect> for JsonLike { + fn as_visitor(&mut self) -> Visitor<'_, 'ctx, SyncEffect> { + self + } } any_trait! { impl['a, 'ctx] JsonLike = [ - dyn Value<'a, OwnedStatic<bool>> + 'a, - dyn Sequence<'ctx> + 'a, + dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Sequence<'ctx, SyncEffect> + 'a, ] } -impl Value<'_, OwnedStatic<bool>> for JsonLike { - fn visit(&mut self, value: OwnedStatic<bool>) -> ControlFlowFor<'_> { +impl<'ctx> Value<'ctx, OwnedStatic<bool>, SyncEffect> for JsonLike { + fn visit<'a>(&'a mut self, value: OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { self.0.push_str(&format!("{}", value.0)); ControlFlow::Continue(()) } } -impl<'ctx> Sequence<'ctx> for JsonLike { +impl<'ctx> Sequence<'ctx, SyncEffect> for JsonLike { fn visit<'a>( &'a mut self, - scope: &'a mut dyn SequenceScope<'ctx>, - ) -> ControlFlowFor<'a, SyncEffect> { + scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { self.0.push_str("["); while let ControlFlow::Continue(treaty::protocol::visitor::Status::Continue) = scope.next(self) diff --git a/tests/hook.rs b/tests/hook.rs index 2ad90d5..7746ab1 100644 --- a/tests/hook.rs +++ b/tests/hook.rs @@ -1,10 +1,11 @@ -use std::{future::Future, marker::PhantomData, pin::Pin, thread::yield_now, time::Duration}; +use std::{future::Future, marker::PhantomData, pin::Pin, thread::yield_now, time::Duration, ops::ControlFlow}; use treaty::{ any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId}, build_with, into_walker, protocol::{ - visitor::Value, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, Visitor, any_t, any_trait_send_obj, + any_t, as_obj, visitor::Value, AsObj, AsyncEffect, Yield, Effect, SyncEffect, + Visitor, EffectAnyTrait, }, Build, Builder, Walker, }; @@ -20,13 +21,22 @@ fn demo() { todo!(); } +#[no_mangle] +fn invert(x: bool) -> bool { + let hook = Hook { + inner: into_walker(x), + _marker: PhantomData, + }; + build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap() +} + struct Hook<T, Effect> { inner: T, _marker: PhantomData<fn() -> Effect>, } -struct VisitorHook<'a, 'ctx: 'a, E: Effect<'ctx>> { - inner: any_trait_send_obj::T<'a, 'ctx, E::VisitorHkt>, +struct VisitorHook<'a, 'ctx: 'a, E: EffectAnyTrait<'ctx>> { + inner: as_obj::T<'a, 'ctx, E::AnyTrait>, } impl<'ctx, T: Walker<'ctx, Effect = AsyncEffect> + Send> Walker<'ctx> for Hook<T, AsyncEffect> @@ -43,15 +53,13 @@ where fn walk<'a>( self, visitor: Visitor<'a, 'ctx, T::Effect>, - ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> + ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect> where Self: 'a, - 'ctx: 'a + 'ctx: 'a, { Box::pin(async move { - let mut visitor = VisitorHook::<Self::Effect> { - inner: visitor, - }; + let mut visitor = VisitorHook::<Self::Effect> { inner: visitor }; let flow = self.inner.walk(&mut visitor); @@ -70,7 +78,7 @@ impl<'ctx, T: Walker<'ctx, Effect = SyncEffect>> Walker<'ctx> for Hook<T, SyncEf fn walk<'a>( self, visitor: Visitor<'a, 'ctx, T::Effect>, - ) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error> + ) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect> where Self: 'a, 'ctx: 'a, @@ -81,7 +89,7 @@ impl<'ctx, T: Walker<'ctx, Effect = SyncEffect>> Walker<'ctx> for Hook<T, SyncEf } } -impl<'b, 'ctx: 'b, E: Effect<'ctx>> AnyTrait<'ctx> for VisitorHook<'b, 'ctx, E> { +impl<'b, 'ctx: 'b, E: Effect<'ctx, ControlFlow<(), ()>>> AnyTrait<'ctx> for VisitorHook<'b, 'ctx, E> { fn upcast_to_id<'a>( &'a self, id: treaty::any::LtTypeId<'ctx>, @@ -94,6 +102,7 @@ impl<'b, 'ctx: 'b, E: Effect<'ctx>> AnyTrait<'ctx> for VisitorHook<'b, 'ctx, E> } } + #[inline] fn upcast_to_id_mut<'a>( &'a mut self, id: treaty::any::LtTypeId<'ctx>, @@ -116,16 +125,19 @@ impl<'b, 'ctx: 'b, E: Effect<'ctx>> AnyTrait<'ctx> for VisitorHook<'b, 'ctx, E> } } -impl<'b, 'ctx: 'b, E: Effect<'ctx>> Value<'ctx, OwnedStatic<bool>, E> for VisitorHook<'b, 'ctx, E> { +impl<'b, 'ctx: 'b, E: Effect<'ctx, ControlFlow<(), ()>>> Value<'ctx, OwnedStatic<bool>, E> for VisitorHook<'b, 'ctx, E> { #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a { + fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + where + 'ctx: 'a, + { let visitor = self .inner .as_obj_mut() .upcast_mut::<dyn Value<'ctx, OwnedStatic<bool>, E> + 'a>() .unwrap(); - println!("Hooked bool: {}", value); + // println!("Hooked bool: {}", value); visitor.visit(OwnedStatic(!value)) } } |