added option builder
| -rw-r--r-- | src/any/static_wrapper.rs | 12 | ||||
| -rw-r--r-- | src/build.rs | 13 | ||||
| -rw-r--r-- | src/build/builders/core.rs | 2 | ||||
| -rw-r--r-- | src/build/builders/core/array.rs | 26 | ||||
| -rw-r--r-- | src/build/builders/core/bool.rs | 20 | ||||
| -rw-r--r-- | src/build/builders/core/option.rs | 327 | ||||
| -rw-r--r-- | src/build/builders/core/variant.rs | 146 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize.rs | 33 | ||||
| -rw-r--r-- | src/build/builders/serde/deserialize_seed.rs | 30 | ||||
| -rw-r--r-- | src/effect.rs | 110 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/protocol.rs | 138 | ||||
| -rw-r--r-- | src/protocol/visitor/request_hint.rs | 8 | ||||
| -rw-r--r-- | src/protocol/visitor/sequence.rs | 12 | ||||
| -rw-r--r-- | src/protocol/visitor/tagged.rs | 13 | ||||
| -rw-r--r-- | src/protocol/visitor/value.rs | 51 | ||||
| -rw-r--r-- | src/protocol/walker/hint.rs | 3 | ||||
| -rw-r--r-- | src/walk.rs | 5 | ||||
| -rw-r--r-- | src/walk/walkers/core/array.rs | 4 | ||||
| -rw-r--r-- | src/walk/walkers/core/bool.rs | 12 | ||||
| -rw-r--r-- | tests/demo.rs | 20 | ||||
| -rw-r--r-- | tests/hook.rs | 37 |
22 files changed, 790 insertions, 233 deletions
diff --git a/src/any/static_wrapper.rs b/src/any/static_wrapper.rs index d167257..511982a 100644 --- a/src/any/static_wrapper.rs +++ b/src/any/static_wrapper.rs @@ -62,3 +62,15 @@ nameable! { impl [T] for BoxedStatic<T> where { T: ?Sized + 'static } impl [T] where BoxedStatic<T> { T: ?Sized + 'static } } + +#[derive(Debug)] +pub enum BorrowedStaticValue<'ctx, T: ?Sized + 'static> { + Ctx(&'ctx T), + Static(&'static T), +} + +#[derive(Debug)] +pub enum BorrowedMutStaticValue<'ctx, T: ?Sized + 'static> { + Ctx(&'ctx mut T), + Static(&'static mut T), +} diff --git a/src/build.rs b/src/build.rs index b75fa6b..7ac87fd 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,7 +1,8 @@ pub mod builders; use crate::{ - protocol::{AsObj as _, Effect, EffectAnyTrait, SyncEffect, Visitor, Yield}, + effect::{AsObj as _, Effect, EffectAnyTrait, SyncEffect, Yield}, + protocol::Visitor, Walker, }; @@ -41,7 +42,9 @@ pub trait Builder<'ctx, E: EffectAnyTrait<'ctx>>: AsVisitor<'ctx, E> { /// /// If an error happened with the builder during the walk /// it will be reported here. - fn build<'a>(self) -> Yield<'a, 'ctx, Result<Self::Value, Self::Error>, Self::Effect> where Self: 'a; + fn build<'a>(self) -> Yield<'a, 'ctx, Result<Self::Value, Self::Error>, Self::Effect> + where + Self: 'a; } pub trait AsVisitor<'ctx, E: EffectAnyTrait<'ctx>> { @@ -93,7 +96,11 @@ where builder.build().map_err(BuildError::Builder) } -pub fn build_with<'ctx, B: Builder<'ctx, SyncEffect, Effect = 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 diff --git a/src/build/builders/core.rs b/src/build/builders/core.rs index 7ea094a..8b4fb45 100644 --- a/src/build/builders/core.rs +++ b/src/build/builders/core.rs @@ -1,2 +1,4 @@ pub mod array; pub mod bool; +pub mod option; +// pub mod variant; diff --git a/src/build/builders/core/array.rs b/src/build/builders/core/array.rs index 34b8f65..ae4c279 100644 --- a/src/build/builders/core/array.rs +++ b/src/build/builders/core/array.rs @@ -2,15 +2,13 @@ use core::{marker::PhantomData, mem::MaybeUninit, ops::ControlFlow}; use crate::{ any_trait, - protocol::{ - visitor::{Sequence, SequenceScope, Status}, - AsObj as _, Yield, Effect, SyncEffect, EffectAnyTrait, - }, + effect::{AsObj as _, Effect, EffectAnyTrait, SyncEffect, Yield}, + protocol::visitor::{Sequence, SequenceScope, Status}, AsVisitor, DefaultBuilder, }; #[cfg(feature = "alloc")] -use crate::protocol::AsyncEffect; +use crate::effect::AsyncEffect; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; @@ -46,7 +44,10 @@ where type Value = [B::Value; N]; - fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { + 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)); } @@ -75,7 +76,7 @@ where 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> + B: crate::Builder<'ctx, SyncEffect, Effect = SyncEffect>, { fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { self @@ -97,13 +98,16 @@ any_trait! { // ] // } -impl<'ctx, B: crate::DefaultBuilder<'ctx, E>, const N: usize, E: EffectAnyTrait<'ctx>> Sequence<'ctx, SyncEffect> - for Builder<'ctx, B, N, E> +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> + B: crate::Builder<'ctx, E, Effect = SyncEffect>, { #[inline] - fn visit<'a>(&'a mut self, scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + fn visit<'a>( + &'a mut self, + scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> where 'ctx: 'a, { diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs index c9c0be9..3becdae 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -3,7 +3,8 @@ use core::{marker::PhantomData, ops::ControlFlow}; use crate::{ any::static_wrapper::OwnedStatic, any_trait, - protocol::{visitor::Value, AsObj, AsyncEffect, Yield, Effect, SyncEffect}, + effect::{AsObj, AsyncEffect, Effect, SyncEffect, Yield}, + protocol::visitor::Value, AsVisitor, }; @@ -30,7 +31,10 @@ where type Value = bool; #[inline] - fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { + fn build<'a>(self) -> Result<Self::Value, Self::Error> + where + Self: 'a, + { self.0.ok_or(Error::Incomplete) } @@ -57,16 +61,16 @@ impl<'ctx> AsVisitor<'ctx, AsyncEffect> for Builder<AsyncEffect> { any_trait! { impl['a, 'ctx, E] Builder<E> = [ - dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + 'a, ] } -impl<'ctx, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> for Builder<E> { +impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> for Builder<E> { #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> - where - 'ctx: 'a, - { + fn visit( + &'a mut self, + OwnedStatic(value): OwnedStatic<bool>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { self.0 = Some(value); ControlFlow::Continue(()) } diff --git a/src/build/builders/core/option.rs b/src/build/builders/core/option.rs new file mode 100644 index 0000000..00c79c9 --- /dev/null +++ b/src/build/builders/core/option.rs @@ -0,0 +1,327 @@ +use core::{marker::PhantomData, ops::ControlFlow}; + +use crate::{ + any::static_wrapper::{BorrowedStatic, BorrowedStaticValue, OwnedStatic, TempBorrowedStatic}, + any_trait, + effect::{AsyncEffect, AsyncSendEffect, EffectAnyTrait, SyncEffect, Yield}, + protocol::visitor::{Tagged, TaggedScope, Value}, + AsVisitor, +}; + +impl<'ctx, T, E> crate::Build<'ctx, E> for Option<T> +where + E: EffectAnyTrait<'ctx>, + Builder<'ctx, T::Builder, E>: AsVisitor<'ctx, E>, + T: crate::Build<'ctx, E>, +{ + type Builder = Builder<'ctx, T::Builder, E>; +} + +pub struct Builder<'ctx, B: crate::Builder<'ctx, E>, E: EffectAnyTrait<'ctx>> { + value: Option<Result<Option<B::Value>, Error<'ctx, B::Error>>>, + ignore_missing: bool, + _marker: PhantomData<fn() -> (&'ctx (), E)>, +} + +#[derive(Default)] +pub enum IgnoreMissing { + #[default] + Yes, + No, +} + +#[derive(Debug)] +pub enum Error<'ctx, T> { + Missing, + VariantNone, + VariantSome(T), + UnknownVariantName(Option<BorrowedStaticValue<'ctx, str>>), + UnknownVariantNum(Option<u8>), + NoVariantGiven, +} + +impl<'ctx, B, E> crate::Builder<'ctx, E> for Builder<'ctx, B, E> +where + E: EffectAnyTrait<'ctx>, + Self: AsVisitor<'ctx, E>, + B: crate::Builder<'ctx, E>, +{ + type Error = Error<'ctx, B::Error>; + + type Value = Option<B::Value>; + + #[inline] + fn build<'a>(self) -> Result<Self::Value, Self::Error> + where + Self: 'a, + { + match self.value { + Some(value) => value, + None if self.ignore_missing => Ok(None), + None => Err(Error::Missing), + } + } + + type Seed = IgnoreMissing; + + fn from_seed(seed: Self::Seed) -> Self { + Self { + value: None, + ignore_missing: match seed { + IgnoreMissing::Yes => true, + IgnoreMissing::No => false, + }, + _marker: PhantomData, + } + } + + type Effect = SyncEffect; +} + +impl<'ctx, B: crate::Builder<'ctx, SyncEffect>> AsVisitor<'ctx, SyncEffect> + for Builder<'ctx, B, SyncEffect> +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { + self + } +} + +impl<'ctx, B: crate::Builder<'ctx, AsyncEffect>> AsVisitor<'ctx, AsyncEffect> + for Builder<'ctx, B, AsyncEffect> +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { + self + } +} + +impl<'ctx, B> AsVisitor<'ctx, AsyncSendEffect> for Builder<'ctx, B, AsyncSendEffect> +where + B: crate::Builder<'ctx, AsyncSendEffect>, + <B as crate::Builder<'ctx, AsyncSendEffect>>::Value: Send, + <B as crate::Builder<'ctx, AsyncSendEffect>>::Error: Send, +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncSendEffect> { + self + } +} + +any_trait! { + impl['a, 'ctx, B] Builder<'ctx, B, SyncEffect> = [ + ] where B: crate::Builder<'ctx, SyncEffect> +} + +any_trait! { + impl['a, 'ctx, B] Builder<'ctx, B, AsyncEffect> = [ + ] where B: crate::Builder<'ctx, AsyncEffect> +} + +any_trait! { + impl['a, 'ctx, B] Builder<'ctx, B, AsyncSendEffect> = [ + ] where B: crate::Builder<'ctx, AsyncSendEffect> +} + +pub mod symbol { + use crate::symbol::Symbol; + + pub const KEY: Symbol = Symbol::new("Key"); + pub const TYPE: Symbol = Symbol::new("Type"); + pub const VARIANT: Symbol = Symbol::new("Variant"); +} + +impl<'ctx, B> Tagged<'ctx, SyncEffect> for Builder<'ctx, B, SyncEffect> +where + B: crate::DefaultBuilder<'ctx, SyncEffect, Effect = SyncEffect>, +{ + fn visit<'a>( + &'a mut self, + scope: &'a mut dyn TaggedScope<'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { + match scope.kind() { + symbol::KEY | symbol::VARIANT => { + // This tag is the variant name/number. + let mut variant = VariantVisitor::<'ctx, B::Error> { value: None }; + scope.tag(&mut variant)?; + let variant = match variant.value { + Some(Ok(value)) => value, + Some(Err(error)) => { + self.value = Some(Err(error)); + return ControlFlow::Break(()); + } + None => { + self.value = Some(Err(Error::NoVariantGiven)); + return ControlFlow::Break(()); + } + }; + + match variant { + Variant::None => { + // Nothing more needs to be done. + self.value = Some(Ok(None)); + ControlFlow::Continue(()) + } + Variant::Some => { + // Now build a T. + let mut builder = B::default(); + scope.value(builder.as_visitor())?; + match builder.build() { + Ok(value) => { + self.value = Some(Ok(Some(value))); + ControlFlow::Continue(()) + } + Err(error) => { + self.value = Some(Err(Error::VariantSome(error))); + ControlFlow::Break(()) + } + } + } + } + } + _ => { + // Ignore any other tags and just use the value. + scope.value(self) + } + } + } +} + +enum Variant { + None, + Some, +} + +pub struct VariantVisitor<'ctx, T> { + value: Option<Result<Variant, Error<'ctx, T>>>, +} + +any_trait! { + impl['a, 'ctx, T] VariantVisitor<'ctx, T> = [ + dyn Value<'a, 'ctx, TempBorrowedStatic<'a, str>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, BorrowedStatic<'ctx, str>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<&'static str>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<u8>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<u16>, SyncEffect> + 'a, + ] +} + +impl<'a, 'ctx: 'a, T> Value<'a, 'ctx, TempBorrowedStatic<'a, str>, SyncEffect> + for VariantVisitor<'ctx, T> +{ + fn visit( + &'a mut self, + TempBorrowedStatic(value): TempBorrowedStatic<'a, str>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { + match value { + "None" => { + self.value = Some(Ok(Variant::None)); + ControlFlow::Continue(()) + } + "Some" => { + self.value = Some(Ok(Variant::Some)); + ControlFlow::Continue(()) + } + _ => { + self.value = Some(Err(Error::UnknownVariantName(None))); + ControlFlow::Break(()) + } + } + } +} + +impl<'a, 'ctx: 'a, T> Value<'a, 'ctx, BorrowedStatic<'ctx, str>, SyncEffect> + for VariantVisitor<'ctx, T> +{ + fn visit( + &'a mut self, + BorrowedStatic(value): BorrowedStatic<'ctx, str>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { + match value { + "None" => { + self.value = Some(Ok(Variant::None)); + ControlFlow::Continue(()) + } + "Some" => { + self.value = Some(Ok(Variant::Some)); + ControlFlow::Continue(()) + } + value => { + self.value = Some(Err(Error::UnknownVariantName(Some( + BorrowedStaticValue::Ctx(value), + )))); + ControlFlow::Break(()) + } + } + } +} + +impl<'a, 'ctx: 'a, T> Value<'a, 'ctx, OwnedStatic<&'static str>, SyncEffect> + for VariantVisitor<'ctx, T> +{ + fn visit( + &'a mut self, + OwnedStatic(value): OwnedStatic<&'static str>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { + match value { + "None" => { + self.value = Some(Ok(Variant::None)); + ControlFlow::Continue(()) + } + "Some" => { + self.value = Some(Ok(Variant::Some)); + ControlFlow::Continue(()) + } + value => { + self.value = Some(Err(Error::UnknownVariantName(Some( + BorrowedStaticValue::Static(value), + )))); + ControlFlow::Break(()) + } + } + } +} + +impl<'a, 'ctx: 'a, T> Value<'a, 'ctx, OwnedStatic<u8>, SyncEffect> for VariantVisitor<'ctx, T> { + fn visit( + &'a mut self, + OwnedStatic(value): OwnedStatic<u8>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { + match value { + 0 => { + self.value = Some(Ok(Variant::None)); + ControlFlow::Continue(()) + } + 1 => { + self.value = Some(Ok(Variant::Some)); + ControlFlow::Continue(()) + } + value => { + self.value = Some(Err(Error::UnknownVariantNum(Some(value)))); + ControlFlow::Break(()) + } + } + } +} + +impl<'a, 'ctx: 'a, T> Value<'a, 'ctx, OwnedStatic<u16>, SyncEffect> for VariantVisitor<'ctx, T> { + fn visit( + &'a mut self, + OwnedStatic(value): OwnedStatic<u16>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { + match value { + 0 => { + self.value = Some(Ok(Variant::None)); + ControlFlow::Continue(()) + } + 1 => { + self.value = Some(Ok(Variant::Some)); + ControlFlow::Continue(()) + } + value => { + self.value = Some(Err(Error::UnknownVariantNum(value.try_into().ok()))); + ControlFlow::Break(()) + } + } + } +} diff --git a/src/build/builders/core/variant.rs b/src/build/builders/core/variant.rs new file mode 100644 index 0000000..5104a2e --- /dev/null +++ b/src/build/builders/core/variant.rs @@ -0,0 +1,146 @@ +use core::{marker::PhantomData, ops::ControlFlow}; + +use crate::{ + any::static_wrapper::OwnedStatic, + any_trait, + effect::{AsyncEffect, AsyncSendEffect, EffectAnyTrait, SyncEffect, Yield}, + protocol::visitor::{Tagged, TaggedScope, Value}, + AsVisitor, +}; + +pub struct VariantInfo<'ctx> { + pub +} + +pub struct Builder<'ctx, E: EffectAnyTrait<'ctx>> { + value: Option<Option<B::Value>>, + ignore_missing: bool, + _marker: PhantomData<fn() -> (&'ctx (), E)>, +} + +#[derive(Default)] +pub enum IgnoreMissing { + #[default] + Yes, + No, +} + +#[derive(Debug)] +pub enum Error<T> { + Missing, + VariantNone, + VariantSome(T), +} + +impl<'ctx, B, E> crate::Builder<'ctx, E> for Builder<'ctx, B, E> +where + E: EffectAnyTrait<'ctx>, + Self: AsVisitor<'ctx, E>, + B: crate::Builder<'ctx, E>, +{ + type Error = Error<B::Error>; + + type Value = Option<B::Value>; + + #[inline] + fn build<'a>(self) -> Result<Self::Value, Self::Error> + where + Self: 'a, + { + if self.ignore_missing { + Ok(self.value.flatten()) + } else { + self.value.ok_or(Error::Missing) + } + } + + type Seed = IgnoreMissing; + + fn from_seed(seed: Self::Seed) -> Self { + Self { + value: None, + ignore_missing: match seed { + IgnoreMissing::Yes => true, + IgnoreMissing::No => false, + }, + _marker: PhantomData, + } + } + + type Effect = SyncEffect; +} + +impl<'ctx, B: crate::Builder<'ctx, SyncEffect>> AsVisitor<'ctx, SyncEffect> + for Builder<'ctx, B, SyncEffect> +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, SyncEffect> { + self + } +} + +impl<'ctx, B: crate::Builder<'ctx, AsyncEffect>> AsVisitor<'ctx, AsyncEffect> + for Builder<'ctx, B, AsyncEffect> +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncEffect> { + self + } +} + +impl<'ctx, B> AsVisitor<'ctx, AsyncSendEffect> for Builder<'ctx, B, AsyncSendEffect> +where + B: crate::Builder<'ctx, AsyncSendEffect>, + <B as crate::Builder<'ctx, AsyncSendEffect>>::Value: Send, +{ + fn as_visitor(&mut self) -> crate::protocol::Visitor<'_, 'ctx, AsyncSendEffect> { + self + } +} + +any_trait! { + impl['a, 'ctx, B] Builder<'ctx, B, SyncEffect> = [ + ] where B: crate::Builder<'ctx, SyncEffect> +} + +any_trait! { + impl['a, 'ctx, B] Builder<'ctx, B, AsyncEffect> = [ + ] where B: crate::Builder<'ctx, AsyncEffect> +} + +any_trait! { + impl['a, 'ctx, B] Builder<'ctx, B, AsyncSendEffect> = [ + ] where B: crate::Builder<'ctx, AsyncSendEffect> +} + +pub mod symbol { + use crate::symbol::Symbol; + + pub const TYPE: Symbol = Symbol::new("Type"); + pub const VARIANT: Symbol = Symbol::new("Variant"); +} + +impl<'ctx, B> Tagged<'ctx, SyncEffect> for Builder<'ctx, B, SyncEffect> +where + B: crate::Builder<'ctx, SyncEffect>, +{ + fn visit<'a>( + &'a mut self, + scope: &'a mut dyn TaggedScope<'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + where + 'ctx: 'a, + { + match scope.kind() { + symbol::TYPE => { + // The type info doesn't matter, just move on to the value. + scope.value(self)?; + }, + symbol::VARIANT => { + // We need to check the variant id. + // let mut variant = VariantBuilder::from_seed(()); + }, + _ => {} + } + + todo!(); + } +} diff --git a/src/build/builders/serde/deserialize.rs b/src/build/builders/serde/deserialize.rs index 8a9fa3e..1daa30f 100644 --- a/src/build/builders/serde/deserialize.rs +++ b/src/build/builders/serde/deserialize.rs @@ -7,10 +7,8 @@ use serde::{de::SeqAccess, forward_to_deserialize_any, Deserialize, Deserializer use crate::{ any::static_wrapper::OwnedStatic, any_trait, - protocol::{ - visitor::{Sequence, SequenceScope, Status, Value}, - AsObj, AsyncEffect, Yield, Effect, SyncEffect, - }, + effect::{AsObj, AsyncEffect, Effect, SyncEffect, Yield}, + protocol::visitor::{Sequence, SequenceScope, Status, Value}, AsVisitor, Builder as _, }; @@ -25,7 +23,8 @@ 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, ControlFlow<(), ()>>> 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 +32,10 @@ where type Value = T; - fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { + fn build<'a>(self) -> Result<Self::Value, Self::Error> + where + Self: 'a, + { self.0 } @@ -60,7 +62,7 @@ impl<'ctx, T: Deserialize<'ctx> + Send> AsVisitor<'ctx, AsyncEffect> for Builder any_trait! { impl['a, 'ctx, T: Deserialize<'ctx>, E] Builder<T, E> = [ - dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + 'a, dyn Sequence<'ctx, SyncEffect> + 'a, ] } @@ -70,12 +72,14 @@ enum InjectedValue<'a, 'ctx> { Sequence(&'a mut dyn SequenceScope<'ctx, SyncEffect>), } -impl<'ctx, T: Deserialize<'ctx>, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> for Builder<T, E> { +impl<'a, 'ctx: 'a, T: Deserialize<'ctx>, E> Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + for Builder<T, E> +{ #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> - where - 'ctx: 'a, - { + fn visit( + &'a mut self, + OwnedStatic(value): OwnedStatic<bool>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { self.0 = T::deserialize(InjectedValue::Bool(value)); if self.0.is_err() { @@ -88,7 +92,10 @@ impl<'ctx, T: Deserialize<'ctx>, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> f 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, SyncEffect>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + fn visit<'a>( + &'a mut self, + scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> where 'ctx: 'a, { diff --git a/src/build/builders/serde/deserialize_seed.rs b/src/build/builders/serde/deserialize_seed.rs index 23434cf..dce34c0 100644 --- a/src/build/builders/serde/deserialize_seed.rs +++ b/src/build/builders/serde/deserialize_seed.rs @@ -10,10 +10,8 @@ use serde::{ use crate::{ any::static_wrapper::OwnedStatic, any_trait, - protocol::{ - visitor::{Sequence, SequenceScope, Status, Value}, - AsObj, AsyncEffect, Yield, Effect, SyncEffect, - }, + effect::{AsObj, AsyncEffect, Effect, SyncEffect, Yield}, + protocol::visitor::{Sequence, SequenceScope, Status, Value}, AsVisitor, Builder as _, }; @@ -46,12 +44,14 @@ impl<'ctx, T: DeserializeSeed<'ctx>, E: Effect<'ctx, ControlFlow<(), ()>>> crate where Self: AsVisitor<'ctx, E>, { - type Error = Error<T>; type Value = T::Value; - fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { + fn build<'a>(self) -> Result<Self::Value, Self::Error> + where + Self: 'a, + { self.0 } @@ -82,7 +82,7 @@ where any_trait! { impl['a, 'ctx, T: DeserializeSeed<'ctx>, E] Builder<'ctx, T, E> = [ - dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + 'a, dyn Sequence<'ctx, SyncEffect> + 'a, ] } @@ -93,15 +93,14 @@ enum InjectedValue<'a, 'ctx, T> { Extra(PhantomData<T>), } -impl<'ctx, T: DeserializeSeed<'ctx>, E> Value<'ctx, OwnedStatic<bool>, SyncEffect> for Builder<'ctx, T, E> { +impl<'a, 'ctx: 'a, T: DeserializeSeed<'ctx>, E> Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + for Builder<'ctx, T, E> +{ #[inline] - fn visit<'a>( + fn visit( &'a mut self, OwnedStatic(bool_value): OwnedStatic<bool>, - ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> - where - 'ctx: 'a, - { + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { let pending = core::mem::replace(&mut self.0, Err(Error::Incomplete)); let Err(Error::Pending(value)) = pending else { todo!() @@ -119,7 +118,10 @@ impl<'ctx, T: DeserializeSeed<'ctx>, E> Value<'ctx, OwnedStatic<bool>, SyncEffec 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, SyncEffect>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> + fn visit<'a>( + &'a mut self, + scope: &'a mut dyn SequenceScope<'ctx, SyncEffect>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> where 'ctx: 'a, { diff --git a/src/effect.rs b/src/effect.rs new file mode 100644 index 0000000..dd8b971 --- /dev/null +++ b/src/effect.rs @@ -0,0 +1,110 @@ +use crate::{any::AnyTrait, hkt, type_class}; + +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> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { + fn as_obj(&self) -> &dyn AnyTrait<'ctx> { + *self + } + + fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> { + *self + } + + fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> { + self + } +} + +impl<'a, 'ctx: 'a> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) { + fn as_obj(&self) -> &dyn AnyTrait<'ctx> { + *self + } + + fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> { + *self + } + + fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> { + self + } +} + +type_class!(for<'lt, 'ctx> pub as_obj: AsObj<'lt, 'ctx>); +type_class!(for<'lt, 'ctx> pub any_t); + +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>; +} + +/// 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!((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 SyncYield[T] => T); + +impl<'ctx, T> Effect<'ctx, T> for SyncEffect { + type Yield = SyncYield<'ctx, T>; +} + +impl<'ctx> EffectAnyTrait<'ctx> for SyncEffect { + type AnyTrait = AnyTraitObj<'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 AsyncYield[T] => + core::pin::Pin< + Box<dyn core::future::Future<Output = T> + 'a>, + > +); + +#[cfg(feature = "alloc")] +pub enum AsyncEffect {} + +#[cfg(feature = "alloc")] +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>; +} @@ -9,6 +9,7 @@ extern crate alloc; pub mod any; mod build; +pub mod effect; pub mod hkt; pub mod protocol; pub mod symbol; diff --git a/src/protocol.rs b/src/protocol.rs index 4ad6d8d..605551a 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -1,3 +1,22 @@ +//! A collection of built in protocols between walkers and visitors. +//! +//! Treaty has not set data model. Instead, this module contains a set of basic protocols +//! walkers and visitors can use to exchange information. +//! +//! | Rust Type (`T`) | Protocol | +//! |-----------|----------| +//! | `bool` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `i8`, `i16`, `i32`, `i64`, `i128`, `isize` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `u8`, `u16`, `u32`, `u64`, `u128`, `usize` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `f32`, `f64` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `char` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `String` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `Vec<u8>` | [`dyn Value<'_, OwnedStatic<T>, _>`][visitor::Value] | +//! | `&'ctx str` | [`dyn Value<'ctx, BorrowedStatic<'ctx, T>, _>`][visitor::Value] | +//! | `&'ctx [u8]` | [`dyn Value<'ctx, BorrowedStatic<'ctx, T>, _>`][visitor::Value] | +//! +//! +//! //! Interface for interfaces. //! //! ## Design @@ -41,8 +60,11 @@ use core::{ task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }; -use crate::any::AnyTrait; use crate::hkt::{hkt, type_class}; +use crate::{ + any::AnyTrait, + effect::{as_obj, EffectAnyTrait}, +}; pub mod visitor; pub mod walker; @@ -51,115 +73,5 @@ pub mod walker; use alloc::boxed::Box; 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 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> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + 'a) { - fn as_obj(&self) -> &dyn AnyTrait<'ctx> { - *self - } - - fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> { - *self - } - - fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> { - self - } -} - -impl<'a, 'ctx: 'a> AsObj<'a, 'ctx> for &'a mut (dyn AnyTrait<'ctx> + Send + 'a) { - fn as_obj(&self) -> &dyn AnyTrait<'ctx> { - *self - } - - fn as_obj_mut(&mut self) -> &mut dyn AnyTrait<'ctx> { - *self - } - - fn into_obj(self) -> &'a mut dyn AnyTrait<'ctx> { - self - } -} - -type_class!(for<'lt, 'ctx> pub as_obj: AsObj<'lt, 'ctx>); -type_class!(for<'lt, 'ctx> pub any_t); - -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>; -} - -/// 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!((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 SyncYield[T] => T); - -impl<'ctx, T> Effect<'ctx, T> for SyncEffect { - type Yield = SyncYield<'ctx, T>; -} - -impl<'ctx> EffectAnyTrait<'ctx> for SyncEffect { - type AnyTrait = AnyTraitObj<'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 AsyncYield[T] => - core::pin::Pin< - Box<dyn core::future::Future<Output = T> + 'a>, - > -); - -#[cfg(feature = "alloc")] -pub enum AsyncEffect {} - -#[cfg(feature = "alloc")] -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>; -} + as_obj::T<'a, 'ctx, <Effect as EffectAnyTrait<'ctx>>::AnyTrait>; +pub type Walker<'a, 'ctx, Effect> = as_obj::T<'a, 'ctx, <Effect as EffectAnyTrait<'ctx>>::AnyTrait>; diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index d79ef73..c7aa847 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -1,8 +1,9 @@ use core::ops::ControlFlow; use crate::{ + effect::{Effect, SyncEffect, Yield}, nameable, - protocol::{Yield, Effect, SyncEffect, Walker}, + protocol::Walker, }; /// Protocol for requesting a hint from a visitor. @@ -11,7 +12,10 @@ pub trait RequestHint<'a, 'ctx: 'a, E: Effect<'ctx, ControlFlow<(), ()>>> { /// /// `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>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>; + fn request_hint( + &'a mut self, + walker: Walker<'a, 'ctx, E>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>; } nameable! { diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index d345ed1..2a5f9f3 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -1,9 +1,10 @@ use core::ops::ControlFlow; use crate::{ + effect::{any_t, Effect, SyncEffect, Yield}, hkt::hkt, nameable, - protocol::{any_t, walker::HintMeta, Yield, Effect, SyncEffect, Visitor}, + protocol::{walker::HintMeta, Visitor}, }; pub trait Sequence<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> { @@ -33,7 +34,10 @@ pub trait SequenceScope<'ctx, E> where E: Effect<'ctx, ControlFlow<(), Status>>, { - fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> Yield<'a, 'ctx, ControlFlow<(), Status>, E> + fn next<'a>( + &'a mut self, + visitor: Visitor<'a, 'ctx, E>, + ) -> Yield<'a, 'ctx, ControlFlow<(), Status>, E> where 'ctx: 'a; } @@ -55,7 +59,9 @@ pub struct Hint { pub len: (usize, Option<usize>), } -impl<'a, 'ctx: 'a, E: Effect<'ctx, ControlFlow<(), ()>>> HintMeta<'ctx> for dyn Sequence<'ctx, E> + '_ { +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 0bc90a0..9b5caf5 100644 --- a/src/protocol/visitor/tagged.rs +++ b/src/protocol/visitor/tagged.rs @@ -1,9 +1,10 @@ use core::ops::ControlFlow; use crate::{ + effect::{any_t, Effect, SyncEffect, Yield}, hkt::hkt, nameable, - protocol::{any_t, walker::HintMeta, Yield, Effect, SyncEffect, Visitor}, + protocol::{walker::HintMeta, Visitor}, symbol::Symbol, }; @@ -33,11 +34,17 @@ nameable! { pub trait TaggedScope<'ctx, E: Effect<'ctx, ControlFlow<(), ()>>> { fn kind(&mut self) -> Symbol; - fn tag<'a>(&'a mut self, visitor: Visitor<'a, 'ctx, E>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + 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>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + fn value<'a>( + &'a mut self, + visitor: Visitor<'a, 'ctx, E>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> where 'ctx: 'a; } diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index ed3a0bd..20c55d9 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -6,15 +6,16 @@ use core::ops::ControlFlow; use crate::{ any::{TypeName, TypeNameable}, + effect::{any_t, Effect, SyncEffect, Yield}, hkt::hkt, nameable, - protocol::{any_t, walker::HintMeta, Effect, SyncEffect, Yield}, + protocol::walker::HintMeta, }; /// Trait object for the [`Value`] protocol. /// /// Types implementing the [`Value`] protocol will implement this trait. -pub trait Value<'ctx, T, E: Effect<'ctx, ControlFlow<(), ()>>> { +pub trait Value<'a, 'ctx: 'a, 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 @@ -24,21 +25,19 @@ pub trait Value<'ctx, T, E: Effect<'ctx, ControlFlow<(), ()>>> { /// 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) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> - where - 'ctx: 'a; + fn visit(&'a mut self, value: T) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>; } nameable! { pub struct Name['a, 'ctx, T, E]; - impl [T::Name, E] for dyn Value<'ctx, T, E> + 'a where { + impl [T::Name, E] for dyn Value<'a, 'ctx, T, E> + 'a where { T: TypeNameable<'a, 'ctx> + ?Sized, E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a, } - impl [T, E] where dyn Value<'ctx, T::Nameable, E> + 'a { + impl [T, E] where dyn Value<'a, 'ctx, T::Nameable, E> + 'a { T: TypeName<'a, 'ctx> + ?Sized, E: Effect<'ctx, ControlFlow<(), ()>>, 'ctx: 'a, @@ -49,7 +48,7 @@ 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, ControlFlow<(), ()>>> HintMeta<'ctx> - for dyn Value<'ctx, T, E> + 'a + for dyn Value<'a, 'ctx, T, E> + 'a { type Known = KnownHkt<'ctx>; @@ -74,27 +73,21 @@ mod test { fn visit() { struct Visitor(Option<i32>); - impl<'ctx> Value<'ctx, OwnedStatic<i32>> for Visitor { - fn visit<'a>( + impl<'a, 'ctx: 'a> Value<'a, 'ctx, OwnedStatic<i32>, SyncEffect> for Visitor { + fn visit( &'a mut self, OwnedStatic(value): OwnedStatic<i32>, - ) -> core::ops::ControlFlow<()> - where - 'ctx: 'a, - { + ) -> core::ops::ControlFlow<()> { self.0 = Some(value); ControlFlow::Continue(()) } } - impl<'ctx> Value<'ctx, BorrowedStatic<'ctx, i32>> for Visitor { - fn visit<'a>( + impl<'a, 'ctx: 'a> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, SyncEffect> for Visitor { + fn visit( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, i32>, - ) -> core::ops::ControlFlow<()> - where - 'ctx: 'a, - { + ) -> core::ops::ControlFlow<()> { self.0 = Some(*value); ControlFlow::Continue(()) } @@ -129,14 +122,11 @@ mod test { fn visit_borrowed() { struct Visitor<'ctx>(Option<&'ctx mut String>); - impl<'ctx> Value<'ctx, BorrowedMutStatic<'ctx, String>> for Visitor<'ctx> { - fn visit<'a>( + impl<'a, 'ctx> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, SyncEffect> for Visitor<'ctx> { + fn visit( &'a mut self, BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>, - ) -> ControlFlow<()> - where - 'ctx: 'a, - { + ) -> ControlFlow<()> { self.0 = Some(value); ControlFlow::Continue(()) } @@ -165,14 +155,11 @@ mod test { fn visit_borrowed_unsized() { struct Visitor<'ctx>(Option<&'ctx str>); - impl<'ctx> Value<'ctx, BorrowedStatic<'ctx, str>> for Visitor<'ctx> { - fn visit<'a>( + impl<'a, 'ctx: 'a> Value<'a, 'ctx, BorrowedStatic<'ctx, str>, SyncEffect> for Visitor<'ctx> { + fn visit( &'a mut self, BorrowedStatic(value): BorrowedStatic<'ctx, str>, - ) -> ControlFlow<()> - where - 'ctx: 'a, - { + ) -> ControlFlow<()> { self.0 = Some(value); ControlFlow::Continue(()) } diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index 56d5793..46ad675 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -8,8 +8,9 @@ use core::ops::ControlFlow; use crate::{ any::{TypeName, TypeNameable}, + effect::{any_t, Effect, EffectAnyTrait, SyncEffect, Yield}, nameable, - protocol::{any_t, Effect, EffectAnyTrait, SyncEffect, Visitor, Yield}, + protocol::Visitor, }; /// Meta information for the hint. diff --git a/src/walk.rs b/src/walk.rs index 384760a..582af96 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,6 +1,9 @@ pub mod walkers; -use crate::protocol::{Effect, EffectAnyTrait, Visitor, Yield}; +use crate::{ + effect::{Effect, Yield}, + protocol::Visitor, +}; /// A type that can be walked. pub trait Walk<'ctx>: Sized { diff --git a/src/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs index 4154e50..c4b9568 100644 --- a/src/walk/walkers/core/array.rs +++ b/src/walk/walkers/core/array.rs @@ -1,12 +1,12 @@ -use crate::protocol::Effect; use core::{mem::MaybeUninit, ops::ControlFlow}; use crate::{ any_trait, + effect::{Effect, SyncEffect, Yield}, protocol::{ visitor::{RequestHint, Sequence, SequenceScope, Status}, walker::{Hint, HintMeta}, - Yield, SyncEffect, Visitor, + Visitor, }, }; diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs index c51861a..0fd9cbd 100644 --- a/src/walk/walkers/core/bool.rs +++ b/src/walk/walkers/core/bool.rs @@ -1,15 +1,13 @@ -use crate::{ - any::static_wrapper::OwnedStatic, - protocol::{visitor::Value, Effect}, -}; +use crate::{any::static_wrapper::OwnedStatic, protocol::visitor::Value}; use core::{mem::MaybeUninit, ops::ControlFlow}; use crate::{ any_trait, + effect::{Effect, SyncEffect, Yield}, protocol::{ visitor::{RequestHint, Sequence, SequenceScope, Status}, walker::{Hint, HintMeta}, - Yield, SyncEffect, Visitor, + Visitor, }, }; @@ -41,7 +39,9 @@ impl<'ctx> crate::Walker<'ctx> for Walker { 'ctx: 'a, { { - if let Some(object) = visitor.upcast_mut::<dyn Value<'_, OwnedStatic<bool>, SyncEffect> + '_>() { + if let Some(object) = + visitor.upcast_mut::<dyn Value<'_, '_, OwnedStatic<bool>, SyncEffect> + '_>() + { object.visit(OwnedStatic(self.0)); } diff --git a/tests/demo.rs b/tests/demo.rs index c644f73..b6bf557 100644 --- a/tests/demo.rs +++ b/tests/demo.rs @@ -3,10 +3,11 @@ use treaty::{ any::{any_trait, static_wrapper::OwnedStatic}, build, build_with, builders::core::array, + effect::{SyncEffect, Yield}, into_walker, protocol::{ visitor::{Sequence, SequenceScope, Value}, - Yield, SyncEffect, Visitor, + Visitor, }, AsVisitor, Builder, Walk, Walker, }; @@ -132,7 +133,10 @@ impl<'ctx> Builder<'ctx, SyncEffect> for JsonLike { type Value = String; - fn build<'a>(self) -> Result<Self::Value, Self::Error> where Self: 'a { + fn build<'a>(self) -> Result<Self::Value, Self::Error> + where + Self: 'a, + { Ok(self.0) } @@ -153,16 +157,16 @@ impl<'ctx> AsVisitor<'ctx, SyncEffect> for JsonLike { any_trait! { impl['a, 'ctx] JsonLike = [ - dyn Value<'ctx, OwnedStatic<bool>, SyncEffect> + 'a, + dyn Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> + 'a, dyn Sequence<'ctx, SyncEffect> + 'a, ] } -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, - { +impl<'a, 'ctx: 'a> Value<'a, 'ctx, OwnedStatic<bool>, SyncEffect> for JsonLike { + fn visit( + &'a mut self, + value: OwnedStatic<bool>, + ) -> Yield<'a, 'ctx, ControlFlow<(), ()>, SyncEffect> { self.0.push_str(&format!("{}", value.0)); ControlFlow::Continue(()) } diff --git a/tests/hook.rs b/tests/hook.rs index 7746ab1..9dacb62 100644 --- a/tests/hook.rs +++ b/tests/hook.rs @@ -1,12 +1,14 @@ -use std::{future::Future, marker::PhantomData, pin::Pin, thread::yield_now, time::Duration, ops::ControlFlow}; +use std::{ + future::Future, marker::PhantomData, ops::ControlFlow, pin::Pin, thread::yield_now, + time::Duration, +}; use treaty::{ any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId}, - build_with, into_walker, - protocol::{ - any_t, as_obj, visitor::Value, AsObj, AsyncEffect, Yield, Effect, SyncEffect, - Visitor, EffectAnyTrait, - }, + build_with, + effect::{any_t, as_obj, AsObj, AsyncEffect, Effect, EffectAnyTrait, SyncEffect, Yield}, + into_walker, + protocol::{visitor::Value, Visitor}, Build, Builder, Walker, }; @@ -16,7 +18,9 @@ fn demo() { inner: into_walker(true), _marker: PhantomData, }; - let x = build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap(); + // let x = build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap(); + // dbg!(x); + let x = build_with::<<Option<bool> as Build<_>>::Builder, _>(hook).unwrap(); dbg!(x); todo!(); } @@ -89,7 +93,9 @@ impl<'ctx, T: Walker<'ctx, Effect = SyncEffect>> Walker<'ctx> for Hook<T, SyncEf } } -impl<'b, 'ctx: 'b, E: Effect<'ctx, ControlFlow<(), ()>>> 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>, @@ -111,10 +117,10 @@ impl<'b, 'ctx: 'b, E: Effect<'ctx, ControlFlow<(), ()>>> AnyTrait<'ctx> for Visi 'ctx: 'a, { match id { - id if id == LtTypeId::of::<dyn Value<'ctx, OwnedStatic<bool>, E> + 'a>() => { + id if id == LtTypeId::of::<dyn Value<'_, 'ctx, OwnedStatic<bool>, E> + 'a>() => { if self.inner.as_obj_mut().upcast_to_id_mut(id).is_some() { Some(IndirectLtAny::<'a, 'ctx, _>::new::< - dyn Value<'ctx, OwnedStatic<bool>, E> + 'a, + dyn Value<'_, 'ctx, OwnedStatic<bool>, E> + 'a, >(self as _)) } else { None @@ -125,16 +131,21 @@ impl<'b, 'ctx: 'b, E: Effect<'ctx, ControlFlow<(), ()>>> AnyTrait<'ctx> for Visi } } -impl<'b, 'ctx: 'b, E: Effect<'ctx, ControlFlow<(), ()>>> Value<'ctx, OwnedStatic<bool>, E> for VisitorHook<'b, 'ctx, E> { +impl<'a, 'b, 'ctx: 'b + 'a, E: Effect<'ctx, ControlFlow<(), ()>>> Value<'a, 'ctx, OwnedStatic<bool>, E> + for VisitorHook<'b, 'ctx, E> +{ #[inline] - fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E> + fn visit( + &'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>() + .upcast_mut::<dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a>() .unwrap(); // println!("Hooked bool: {}", value); |