enough of the new effects to show perfect code generation!
| -rw-r--r-- | src/build/builders/core/struct.rs | 55 | ||||
| -rw-r--r-- | src/effect.rs | 364 | ||||
| -rw-r--r-- | src/lib.rs | 11 | ||||
| -rw-r--r-- | src/macros/build.rs | 24 | ||||
| -rw-r--r-- | src/protocol/visitor/recoverable.rs | 5 | ||||
| -rw-r--r-- | src/protocol/visitor/sequence.rs | 1 | ||||
| -rw-r--r-- | src/transform.rs | 23 | ||||
| -rw-r--r-- | src/walk.rs | 12 | ||||
| -rw-r--r-- | src/walk/walkers/core/key_value.rs | 32 | ||||
| -rw-r--r-- | src/walk/walkers/core/noop.rs | 9 | ||||
| -rw-r--r-- | src/walk/walkers/core/struct.rs | 73 | ||||
| -rw-r--r-- | src/walk/walkers/core/tag.rs | 9 | ||||
| -rw-r--r-- | src/walk/walkers/core/value.rs | 24 | ||||
| -rw-r--r-- | tests/builder_struct.rs | 9 |
14 files changed, 557 insertions, 94 deletions
diff --git a/src/build/builders/core/struct.rs b/src/build/builders/core/struct.rs index 2da2879..1b5c00a 100644 --- a/src/build/builders/core/struct.rs +++ b/src/build/builders/core/struct.rs @@ -1,3 +1,5 @@ +use core::{marker::PhantomData, ops::ControlFlow}; + use crate::{ any::{OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, any_trait, @@ -83,6 +85,7 @@ where I: StructTypeInfo<'ctx, M, E>, E: Effect, { + #[inline(always)] fn from_seed<'a>(seed: Self::Seed) -> ObjSafe<'a, Self, E> where Self: 'a, @@ -139,11 +142,14 @@ where // This signals to go into map mode for the sequence. self.mode = StructMode::Map; - E::with(NoopVisitor::new(), |noop| { - walker - .walk(DynVisitor(noop)) - .map(|x| x.to_continue().into()) - .into() + E::with(NoopVisitor::new(), |noop, _| { + ( + walker + .walk(DynVisitor(noop)) + .map(|x| x.to_continue().into()) + .into(), + PhantomData, + ) }) .into() } @@ -160,7 +166,44 @@ where &'a mut self, scope: DynSequenceScope<'a, 'ctx, E>, ) -> ObjSafe<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> { - todo!() + match self.mode { + StructMode::Tuple => { + E::ready((self, scope, 0)) + .r#loop(|(this, scope, index)| { + if let Some(marker) = I::marker_from_index(*index) { + // Select the visitor for this field. + let visitor = I::as_visitor(marker, &mut this.builders); + + // For rust analyzer. + let scope: &mut DynSequenceScope<'_, '_, E> = scope; + + scope + .next(visitor) + .map(|flow| match flow { + Flow::Continue => { + *index += 1; + + ControlFlow::Continue(()) + } + Flow::Err => { + ControlFlow::Break(VisitResult::Control(Flow::Err)) + } + Flow::Done => { + ControlFlow::Break(VisitResult::Control(Flow::Done)) + } + }) + .into() + } else { + E::ready(ControlFlow::Break(VisitResult::Control(Flow::Done))).into() + } + }) + .into() + } + StructMode::Map => { + todo!() + } + } + // match self.mode { // StructMode::Tuple => E::wrap(async { // let mut index = 0; diff --git a/src/effect.rs b/src/effect.rs index 9207441..dea709c 100644 --- a/src/effect.rs +++ b/src/effect.rs @@ -1,6 +1,7 @@ use core::{ future::Future, marker::PhantomData, + ops::ControlFlow, pin::{pin, Pin}, ptr, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, @@ -54,6 +55,37 @@ pub trait Adapters<'lt>: Into<ObjSafe<'lt, Self::T, Self::Effect>> + 'lt { where F: FnOnce(Self::T) -> R, 'lt: 'a; + + type AsCtxFor: HktFn<Self::Effect> + HktFnOwn<Self::Effect> + HktFnMut<Self::Effect>; + + fn as_ctx_for<'ctx, 'a, R: 'a, F: 'a>(self, f: F) -> ObjSafe<'a, (Self::T, R), Self::Effect> + where + F: for<'b> FnOnce( + &'b mut Self::T, + PhantomData<&'b &'ctx ()>, + ) -> (ObjSafe<'b, R, Self::Effect>, PhantomData<&'b &'ctx ()>); + + fn then<'ctx, 'a, R: 'a, F: 'a>( + self, + f: F, + ) -> <<Self::AsCtxFor as HktFnOwn<Self::Effect>>::T<Self::T, R, F, &'ctx ()> as ForLtFnOwn< + 'a, + Self::T, + R, + F, + &'a (Self::T, R, F, &'ctx ()), + &'ctx (), + Self::Effect, + >>::T + where + F: for<'b> FnOnce( + Self::T, + PhantomData<&'b &'ctx ()>, + ) -> ObjSafe<'b, R, Self::Effect>; + + fn r#loop<'ctx, 'a, R: 'a, F: 'a>(self, f: F) -> ObjSafe<'a, R, Self::Effect> + where + F: for<'b> FnMut(&'b mut Self::T) -> ObjSafe<'b, ControlFlow<R>, Self::Effect>; } pub trait ForLt<'a, Output: 'a, B> { @@ -68,11 +100,75 @@ pub trait Hkt { type T<Output, B>: for<'a> ForLt<'a, Output, &'a (Output, B), Effect = Self::Effect>; } -pub trait ForLtFn<'a, E: Effect> { - type T<Input: 'a, Output: 'a, F: 'a + for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, E>>: Adapters<'a, Effect = E, T = Output>; +pub trait ForLtFn<'a, Input: 'a, Output: 'a, F: 'a, B, O, E: Effect> +where + F: for<'b> FnOnce( + &'b mut Input, + PhantomData<&'b O>, + ) -> (ObjSafe<'b, Output, E>, PhantomData<&'b O>), +{ + type T: Adapters<'a, Effect = E, T = Output>; +} + +pub trait HktFn<E: Effect> { + type T<Input, Output, F: for<'b> FnOnce(&'b mut Input, PhantomData<&'b B>) -> (ObjSafe<'b, Output, E>, PhantomData<&'b B>), B>: for<'a> ForLtFn<'a, Input, Output, F, &'a (Input, Output, F, B), B, E>; +} + +impl<'b, T, Input: 'b, Output: 'b, ForBound, E: Effect> MutMapFnMut<'b, Input, Output, ForBound, E> + for T +where + T: FnMut(&'b mut Input) -> ObjSafe<'b, Output, E>, +{ + fn call(&mut self, input: &'b mut Input) -> ObjSafe<'b, Output, E> { + self(input) + } +} + +pub trait MutMapFnMut<'b, FIn: 'b, FOut: 'b, ForBound, E: Effect> { + fn call(&mut self, input: &'b mut FIn) -> ObjSafe<'b, FOut, E>; +} + +pub trait ForLtFnMut<'a, FIn: 'a, FOut, Output: 'a, F: 'a, ForBound, E: Effect> +where + for<'b> F: MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), E>, +{ + type T: Adapters<'a, Effect = E, T = Output>; +} + +// pub trait ForLtFnMut<'a, Input: 'a, Output: 'a, F: 'a, B, O, E: Effect> +// where +// F: for<'b> FnMut( +// &'b mut Input, +// PhantomData<&'b O>, +// ) -> (ObjSafe<'b, Output, E>, PhantomData<&'b O>), +// { +// type T: Adapters<'a, Effect = E, T = Output>; +// } + +pub trait HktFnMut<E: Effect> { + type T<FIn, FOut, Output, F: for<'b> MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), E>, ForBound>: for<'a> ForLtFnMut<'a, FIn, FOut, Output, F, &'a (FIn, Output, F, ForBound), E>; } -pub trait HktFn<E: Effect>: for<'a> ForLtFn<'a, E> {} +// pub trait HktFnMut<E: Effect> { +// type T<Input, Output, F: for<'b> FnMut(&'b mut Input, PhantomData<&'b B>) -> (ObjSafe<'b, Output, E>, PhantomData<&'b B>), B>: for<'a> ForLtFnMut<'a, Input, Output, F, &'a (Input, Output, F, B), B, E>; +// } + +pub trait ForLtFnOwn<'a, Input: 'a, Output: 'a, F: 'a, B, O, E: Effect> +where + F: for<'b> FnOnce(Input, PhantomData<&'b O>) -> ObjSafe<'b, Output, E>, +{ + type T: Adapters<'a, Effect = E, T = Output>; +} + +pub trait HktFnOwn<E: Effect> { + type T<Input, Output, F: for<'b> FnOnce(Input, PhantomData<&'b B>) -> ObjSafe<'b, Output, E>, B>: for<'a> ForLtFnOwn<'a, Input, Output, F, &'a (Input, Output, F, B),B, E>; +} + +// pub trait ForLtFn<'a, E: Effect> { +// type T<Input: 'a, Output: 'a, F: 'a + for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, E>>: Adapters<'a, Effect = E, T = Output>; +// } +// +// pub trait HktFn<E: Effect>: for<'a> ForLtFn<'a, E> {} /// Trait for effects. pub trait Effect: Sized + Send + Sync + 'static { @@ -84,13 +180,105 @@ pub trait Effect: Sized + Send + Sync + 'static { type With: HktFn<Self>; - fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> <Self::With as ForLtFn<'a, Self>>::T<T, R, F> + fn with<'ctx, 'a, T: 'a, R: 'a, F: 'a>( + x: T, + f: F, + ) -> <<Self::With as HktFn<Self>>::T<T, R, F, &'ctx ()> as ForLtFn< + 'a, + T, + R, + F, + &'a (T, R, F, &'ctx ()), + &'ctx (), + Self, + >>::T where - F: FnOnce(&mut T) -> ObjSafe<'_, R, Self>; + F: for<'b> FnOnce( + &'b mut T, + PhantomData<&'b &'ctx ()>, + ) -> (ObjSafe<'b, R, Self>, PhantomData<&'b &'ctx ()>); + + fn join<'a, T: 'a>(tuple: T) -> ObjSafe<'a, T::Output, Self> + where + T: Joinable<'a, Self>, + { + T::join(tuple) + } + + fn try_join<'a, T: 'a>(tuple: T) -> ObjSafe<'a, Result<T::Output, T::Error>, Self> + where + T: TryJoinable<'a, Self>, + { + T::try_join(tuple) + } +} + +pub trait Joinable<'a, E: Effect>: Sized { + type Output; + + fn join(tuple: Self) -> ObjSafe<'a, Self::Output, E>; } -pub type ObjSafe<'a, T, E> = - <<<E as Effect>::ObjSafe as Hkt>::T<T, ()> as ForLt<'a, T, &'a (T, ())>>::T; +pub struct Join<T, B>(pub T, pub Marker<B>); + +impl<'a, E: Effect, T0> Joinable<'a, E> for Join<(ObjSafe<'a, T0, E>,), (T0,)> { + fn join(Join((a,), _): Self) -> ObjSafe<'a, (T0,), E> { + a.map(|x| (x,)).into() + } + + type Output = (T0,); +} + +impl<'a, E: Effect, T0, T1> Joinable<'a, E> + for Join<(ObjSafe<'a, T0, E>, ObjSafe<'a, T1, E>), (T0, T1)> +{ + fn join(Join((a, b), _): Self) -> ObjSafe<'a, (T0, T1), E> { + a.then(|a, _| b.map(|b| (a, b)).into()).into() + } + + type Output = (T0, T1); +} + +pub trait TryJoinable<'a, E: Effect>: Sized { + type Output; + + type Error; + + fn try_join(tuple: Self) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E>; +} + +impl<'a, E: Effect, Err, T0, T1> TryJoinable<'a, E> + for Join< + ( + ObjSafe<'a, Result<T0, Err>, E>, + ObjSafe<'a, Result<T1, Err>, E>, + ), + (Err, T0, T1), + > +{ + fn try_join(Join((a, b), _): Self) -> ObjSafe<'a, Result<(T0, T1), Err>, E> { + a.then(|a, _| { + match a { + Ok(a) => b + .map(|b| match b { + Ok(b) => Ok((a, b)), + Err(err) => Err(err), + }) + .into(), + Err(err) => E::ready(Err(err)).into(), + } + // b.map(|b| (a, b)).into() + }) + .into() + } + + type Output = (T0, T1); + + type Error = Err; +} + +pub type ObjSafe<'a, T, E, B = ()> = + <<<E as Effect>::ObjSafe as Hkt>::T<T, B> as ForLt<'a, T, &'a (T, B)>>::T; pub enum Blocking {} @@ -112,14 +300,62 @@ impl<'a, T, B> ForLt<'a, T, &'a (T, B)> for ValueHrt<T, B> { pub enum WithHkt {} -impl HktFn<Blocking> for WithHkt {} +impl HktFnOwn<Blocking> for WithHkt { + type T< + Input, + Output, + F: for<'b> FnOnce(Input, PhantomData<&'b B>) -> ObjSafe<'b, Output, Blocking>, + B, + > = WithHkt; +} -impl<'a> ForLtFn<'a, Blocking> for WithHkt { +impl<'a, Input, Output, F, B> + ForLtFnOwn<'a, Input, Output, F, &'a (Input, Output, F, B), B, Blocking> for WithHkt +where + F: for<'b> FnOnce(Input, PhantomData<&'b B>) -> ObjSafe<'b, Output, Blocking>, +{ + type T = Value<Output>; +} + +impl HktFn<Blocking> for WithHkt { type T< - Input: 'a, - Output: 'a, - F: 'a + for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, Blocking>, - > = Value<Output>; + Input, + Output, + F: for<'b> FnOnce( + &'b mut Input, + PhantomData<&'b B>, + ) -> (ObjSafe<'b, Output, Blocking>, PhantomData<&'b B>), + B, + > = WithHkt; +} + +impl<'a, Input, Output, F, B> ForLtFn<'a, Input, Output, F, &'a (Input, Output, F, B), B, Blocking> + for WithHkt +where + F: for<'b> FnOnce( + &'b mut Input, + PhantomData<&'b B>, + ) -> (ObjSafe<'b, Output, Blocking>, PhantomData<&'b B>), +{ + type T = Value<Output>; +} + +impl HktFnMut<Blocking> for WithHkt { + type T< + FIn, + FOut, + Output, + F: for<'b> MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), Blocking>, + ForBound, + > = WithHkt; +} + +impl<'a, FIn, FOut, Output, F, B> + ForLtFnMut<'a, FIn, FOut, Output, F, &'a (FIn, Output, F, B), Blocking> for WithHkt +where + for<'b> F: MutMapFnMut<'b, FIn, FOut, &'b (FIn, FOut), Blocking>, +{ + type T = Value<Output>; } impl Effect for Blocking { @@ -133,12 +369,27 @@ impl Effect for Blocking { type With = WithHkt; - fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> <Self::With as ForLtFn<'a, Blocking>>::T<T, R, F> + #[inline(always)] + fn with<'ctx, 'a, T: 'a, R: 'a, F: 'a>( + x: T, + f: F, + ) -> <<Self::With as HktFn<Self>>::T<T, R, F, &'ctx ()> as ForLtFn< + 'a, + T, + R, + F, + &'a (T, R, F, &'ctx ()), + &'ctx (), + Self, + >>::T where - F: FnOnce(&mut T) -> ObjSafe<'_, R, Self>, + F: for<'b> FnOnce( + &'b mut T, + PhantomData<&'b &'ctx ()>, + ) -> (ObjSafe<'b, R, Self>, PhantomData<&'b &'ctx ()>), { let mut ctx = x; - f(&mut ctx) + f(&mut ctx, PhantomData).0 } } @@ -158,8 +409,56 @@ impl<'b, U: 'b> Adapters<'b> for Value<U> { { Value(f(self.0)) } + + type AsCtxFor = WithHkt; + + #[inline(always)] + fn as_ctx_for<'ctx, 'a, R: 'a, F: 'a>(self, f: F) -> ObjSafe<'a, (Self::T, R), Blocking> + where + F: for<'c> FnOnce( + &'c mut Self::T, + PhantomData<&'c &'ctx ()>, + ) -> (ObjSafe<'c, R, Self::Effect>, PhantomData<&'c &'ctx ()>), + { + let mut ctx = self.0; + let value = f(&mut ctx, PhantomData).0 .0; + Value((ctx, value)) + } + + fn then<'ctx, 'a, R: 'a, F: 'a>( + self, + f: F, + ) -> <<Self::AsCtxFor as HktFnOwn<Self::Effect>>::T<Self::T, R, F, &'ctx ()> as ForLtFnOwn< + 'a, + Self::T, + R, + F, + &'a (Self::T, R, F, &'ctx ()), + &'ctx (), + Self::Effect, + >>::T + where + F: for<'c> FnOnce( + Self::T, + PhantomData<&'c &'ctx ()>, + ) -> ObjSafe<'c, R, Self::Effect>{ + f(self.0, PhantomData) + } + + #[inline(always)] + fn r#loop<'ctx, 'a, R: 'a, F: 'a>(mut self, mut f: F) -> ObjSafe<'a, R, Blocking> + where + F: for<'c> FnMut(&'c mut Self::T) -> ObjSafe<'c, ControlFlow<R>, Self::Effect>, + { + loop { + if let ControlFlow::Break(value) = f(&mut self.0).0 { + return Value(value); + } + } + } } +/* pub enum Async {} impl Effect for Async { @@ -173,9 +472,20 @@ impl Effect for Async { type With = AsyncWithHkt; - fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> <Self::With as ForLtFn<'a, Self>>::T<T, R, F> + fn with<'a, T: 'a, R: 'a, F: 'a>( + x: T, + f: F, + ) -> <<Self::With as HktFn<Self>>::T<T, R, F, ()> as ForLtFn< + 'a, + T, + R, + F, + &'a (T, R, F, ()), + Self, + >>::T where - F: FnOnce(&mut T) -> ObjSafe<'_, R, Self> { + F: FnOnce(&mut T) -> ObjSafe<'_, R, Self>, + { BoxedFuture(Box::pin(async move { let mut x = x; @@ -211,10 +521,17 @@ impl Hkt for AsyncValueHkt { pub enum AsyncWithHkt {} -impl HktFn<Async> for AsyncWithHkt {} +impl HktFn<Async> for AsyncWithHkt { + type T<Input, Output, F: for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, Async>, B> = + AsyncWithHkt; +} -impl<'a> ForLtFn<'a, Async> for AsyncWithHkt { - type T<Input: 'a, Output: 'a, F: 'a + for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, Async>> = BoxedFuture<'a, Output>; +impl<'a, Input, Output, F, B> ForLtFn<'a, Input, Output, F, &'a (Input, Output, F, B), Async> + for AsyncWithHkt +where + F: for<'b> FnOnce(&'b mut Input) -> ObjSafe<'b, Output, Async>, +{ + type T = BoxedFuture<'a, Output>; } pub struct AsyncValue<T>(pub T); @@ -256,7 +573,7 @@ impl<'b, U: 'b> Adapters<'b> for BoxedFuture<'b, U> { 'b: 'a, { AsyncMap { - map: futures::FutureExt::map(self, f) + map: futures::FutureExt::map(self, f), } } } @@ -284,7 +601,7 @@ where 'b: 'a, { AsyncMap { - map: futures::FutureExt::map(self, f) + map: futures::FutureExt::map(self, f), } } } @@ -325,6 +642,7 @@ impl<'a, T: 'a> From<AsyncValue<T>> for BoxedFuture<'a, T> { BoxedFuture(Box::pin(futures::future::ready(value.0))) } } +*/ /* pub trait ReadyValue: core::future::Future { @@ -137,6 +137,8 @@ macro_rules! Walk { $(pub const $field: usize = Fields::$field as usize;)* } + use $crate::effect::Adapters; + match index { $(fields::$field => { let key_walker = $crate::walkers::core::value::ValueWalker::new(stringify!($field)); @@ -145,7 +147,14 @@ macro_rules! Walk { let walker = $crate::walkers::core::key_value::KeyValueWalker::<$crate::protocol::visitor::TagConst<{ $crate::TAG_FIELD.to_int() }>, _, _>::new($crate::protocol::visitor::TagConst, key_walker, value_walker); - todo!() + $crate::Walker::<'ctx, E>::walk(walker, visitor).map(|result| match result { + Ok(_) => { + Ok($crate::Flow::Continue) + } + Err(err) => { + Err(FieldError(FieldErrorKind::$field(err))) + } + }).into() // E::map($crate::Walker::<'ctx, E>::walk(walker, visitor), |result| match result { // Ok(_) => { diff --git a/src/macros/build.rs b/src/macros/build.rs index 2734d2d..2a45c0a 100644 --- a/src/macros/build.rs +++ b/src/macros/build.rs @@ -44,10 +44,19 @@ macro_rules! Build { type Error = Error; type Seed = ($(<$type as $crate::BuilderTypes>::Seed),*); + #[inline(always)] fn new_builders<'a>(seed: Self::Seed) -> $crate::effect::ObjSafe<'a, Self::Builders, E> { let ($($field),*) = seed; - todo!(); + use $crate::effect::Adapters; + + E::join( + $crate::effect::Join(($(<<$type as $crate::Build<'ctx, M, E>>::Builder as $crate::Builder::<E>>::from_seed($field),)*), $crate::hkt::Marker::default()) + ).map(|($($field,)*)| { + Builders { + $($field),* + } + }).into() // E::wrap(async move { // Builders { @@ -58,8 +67,19 @@ macro_rules! Build { fn from_builders<'a>(builders: Self::Builders) -> $crate::effect::ObjSafe<'a, Result<Self::T, Self::Error>, E> { use $crate::Builder; + use $crate::effect::Adapters; + + E::try_join( + $crate::effect::Join(( + $(builders.$field.build().map(|x| x.map_err(Error::$field)).into(),)* + ), $crate::hkt::Marker::default()) + ).map(|result| match result { + Ok(($($field,)*)) => Ok($name { + $($field),* + }), + Err(err) => Err(err) + }).into() - todo!(); // E::wrap(async { // Ok($name { // $($field: builders.$field.build().await.map_err(Error::$field)?),* diff --git a/src/protocol/visitor/recoverable.rs b/src/protocol/visitor/recoverable.rs index e64820a..6f76d92 100644 --- a/src/protocol/visitor/recoverable.rs +++ b/src/protocol/visitor/recoverable.rs @@ -38,7 +38,10 @@ higher_ranked_type! { } pub trait RecoverableScope<'ctx, E: Effect> { - fn new_walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Status, E>; + fn new_walk<'this: 'effect, 'visitor: 'effect, 'effect>( + &'this mut self, + visitor: DynVisitor<'visitor, 'ctx>, + ) -> ObjSafe<'effect, Status, E>; } pub type DynRecoverableScope<'a, 'ctx, E> = diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index f367ae2..1f2458f 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -86,6 +86,7 @@ impl<E: Effect> HintMeta for SequenceProto<E> { type Effect = E; } +#[inline(always)] pub fn visit_sequence<'a, 'ctx, E: Effect>( visitor: DynVisitor<'a, 'ctx>, scope: DynSequenceScope<'a, 'ctx, E>, diff --git a/src/transform.rs b/src/transform.rs index 91129c7..9f92ba2 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -1,17 +1,32 @@ +use core::marker::PhantomData; + use crate::{ build::Builder, - effect::{Effect, ObjSafe}, + effect::{Adapters, Effect, ObjSafe}, hkt::Marker, Walk, Walker, WalkerTypes, }; -#[inline] +#[inline(always)] #[allow(clippy::type_complexity)] -pub fn transform<'a, 'ctx, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect>( +pub fn transform<'a, 'ctx: 'a, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect>( seed: B::Seed, walker: W, ) -> ObjSafe<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> { - todo!() + B::from_seed(seed) + .as_ctx_for( + #[inline(always)] + move |builder, _| (walker.walk(builder.as_visitor()), PhantomData), + ) + .then(|(builder, walker_result), _| { + builder + .build() + .map(|builder_result| (builder_result, walker_result)) + .into() + }) + .into() + // B::from_seed(seed).map_with(walker, |builder, walker| walker.walk(builder.as_visitor())); + // E::wrap(async { // // Create builder from seed value; // let mut builder = B::from_seed(seed).await; diff --git a/src/walk.rs b/src/walk.rs index a7ace88..a8051fb 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -37,16 +37,16 @@ pub trait Walker<'ctx, E: Effect>: WalkerTypes + Send + Sync { /// Walk the value. /// /// The walker should send data to the `visitor` as it walks the value. - fn walk<'a>( + fn walk<'visitor: 'effect, 'effect>( self, - visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> + visitor: DynVisitor<'visitor, 'ctx>, + ) -> ObjSafe<'effect, Result<Self::Output, Self::Error>, E> where - Self: 'a; + Self: 'effect; } pub trait WalkerObjSafe<'ctx, E: Effect>: Send { - fn walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E> + fn walk<'a, 'b: 'a>(&'a mut self, visitor: DynVisitor<'b, 'ctx>) -> ObjSafe<'b, Flow, E> where Self: 'a; } @@ -107,7 +107,7 @@ impl<W: WalkerTypes> DynWalkerAdapter<W> { impl<'ctx, W: Walker<'ctx, E>, E: Effect> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<W> { #[inline(always)] - fn walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E> + fn walk<'a, 'b: 'a>(&'a mut self, visitor: DynVisitor<'b, 'ctx>) -> ObjSafe<'b, Flow, E> where Self: 'a, { diff --git a/src/walk/walkers/core/key_value.rs b/src/walk/walkers/core/key_value.rs index 987d3bf..9045bf9 100644 --- a/src/walk/walkers/core/key_value.rs +++ b/src/walk/walkers/core/key_value.rs @@ -1,5 +1,7 @@ +use core::marker::PhantomData; + use crate::{ - effect::{Effect, ObjSafe}, + effect::{Adapters, Effect, ObjSafe}, never::Never, protocol::{ visitor::{visit_tag, TagConst, TagError, TagKind, VisitResult}, @@ -52,17 +54,29 @@ where E: Effect, T: TagKind, K: crate::Walker<'ctx, E>, - V: crate::Walker<'ctx, E>, + V: crate::Walker<'ctx, E> + 'ctx, { #[inline(always)] - fn walk<'a>( + fn walk<'b: 'c, 'c>( self, - mut visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> - where - Self: 'a, - { - todo!() + mut visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Result<Self::Output, Self::Error>, E> { + E::ready(visitor) + .as_ctx_for(move |visitor, _| { + ( + self.value_walker + .walk(visitor.cast()) + .map(|result| match result { + Ok(_) => Ok::<_, Self::Error>(()), + Err(_err) => todo!(), + }) + .into(), + PhantomData, + ) + }) + .map(|(_, value)| value) + .into() + // E::wrap(async move { // match visit_tag::<T, E, _>(self.tag, visitor.cast(), NoopWalker::new()).await { // Ok(VisitResult::Skipped(_)) => { diff --git a/src/walk/walkers/core/noop.rs b/src/walk/walkers/core/noop.rs index 4a7f255..21d0880 100644 --- a/src/walk/walkers/core/noop.rs +++ b/src/walk/walkers/core/noop.rs @@ -25,13 +25,10 @@ impl WalkerTypes for NoopWalker { } impl<'ctx, E: Effect> crate::Walker<'ctx, E> for NoopWalker { - fn walk<'a>( + fn walk<'b: 'c, 'c>( self, - _visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> - where - Self: 'a, - { + _visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Result<Self::Output, Self::Error>, E> { E::ready(Ok(())).into() } } diff --git a/src/walk/walkers/core/struct.rs b/src/walk/walkers/core/struct.rs index 46ac3a6..d6c8c4b 100644 --- a/src/walk/walkers/core/struct.rs +++ b/src/walk/walkers/core/struct.rs @@ -1,9 +1,9 @@ -use core::any::TypeId; +use core::{any::TypeId, marker::PhantomData}; use crate::{ any::{AnyTrait, BorrowedStatic, BorrowedStaticHrt}, any_trait, - effect::{Effect, ObjSafe}, + effect::{Adapters, Effect, ObjSafe}, hkt::Marker, never::Never, protocol::{ @@ -122,14 +122,33 @@ where Self: AnyTrait<'ctx> + RecoverableScope<'ctx, E>, { #[inline(always)] - fn walk<'a>( + fn walk<'b: 'c, 'c>( mut self, - mut visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> + mut visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Result<Self::Output, Self::Error>, E> where - Self: 'a, + Self: 'c, { - todo!() + E::ready((self, visitor)) + .as_ctx_for( + #[inline(always)] + |(this, visitor), _| { + ( + RecoverableScope::<'ctx, E>::new_walk::<'_, '_, '_>(this, visitor.cast()), + PhantomData, + ) + }, + ) + .map(|((this, _), _)| match this.error { + Some(err) => Err(StructWalkError { kind: err }), + None => Ok(()), + }) + .into() + + // E::ready(self).as_ctx_for::<'ctx, '_>(|this, _| { + // (RecoverableScope::<'ctx, E>::new_walk::<'_, 'b, '_>(this, visitor), PhantomData) + // }); + // E::wrap(async move { // // Use the recoverable walk to not duplicate the code. // let _ = RecoverableScope::<'ctx, E>::new_walk(&mut self, visitor.cast()).await; @@ -560,7 +579,17 @@ where let index = self.index; self.index += 1; - todo!() + I::walk_field::<E>(index, self.value, visitor) + .map(|result| match result { + Ok(flow) => flow, + Err(err) => { + // Record the error and signal a break. + self.error = Some(StructWalkErrorKind::Field(err)); + Flow::Err + } + }) + .into() + // E::map( // I::walk_field::<E>(index, self.value, visitor), // |result| match result { @@ -582,14 +611,38 @@ where I::T: 'static, { #[inline(always)] - fn new_walk<'a>(&'a mut self, mut visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Status, E> { + fn new_walk<'a: 'c, 'b: 'c, 'c>( + &'a mut self, + mut visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Status, E> { // Reset the errors to default state. self.error = None; // Reset the field index to the default. self.index = 0; - todo!() + E::with( + (self, visitor), + #[inline(always)] + |(this, visitor), _| { + ( + visit_sequence::<E>(visitor.cast(), *this) + .map(|result| { + match result { + VisitResult::Control(Flow::Continue) | VisitResult::Skipped(_) => {} + VisitResult::Control(Flow::Done) => return Ok(()), + VisitResult::Control(Flow::Err) => return Err(()), + } + + Ok(()) + }) + .into(), + PhantomData, + ) + }, + ) + .into() + // E::wrap(async move { // // // We should check if the visitor wants something specific. // // match visit_request_hint::<E>(visitor.cast(), DynWalker(self)).await { diff --git a/src/walk/walkers/core/tag.rs b/src/walk/walkers/core/tag.rs index ff8faa3..d94887d 100644 --- a/src/walk/walkers/core/tag.rs +++ b/src/walk/walkers/core/tag.rs @@ -44,13 +44,10 @@ where &'static T: Into<W>, { #[inline(always)] - fn walk<'a>( + fn walk<'b: 'c, 'c>( mut self, - mut visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> - where - Self: 'a, - { + mut visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Result<Self::Output, Self::Error>, E> { todo!() // E::wrap(async move { // match visit_request_hint::<E>(visitor.cast(), DynWalker(&mut self)).await { diff --git a/src/walk/walkers/core/value.rs b/src/walk/walkers/core/value.rs index 62f5450..eec00b5 100644 --- a/src/walk/walkers/core/value.rs +++ b/src/walk/walkers/core/value.rs @@ -1,6 +1,6 @@ use crate::{ any::{BorrowedStatic, OwnedStatic}, - effect::{Effect, ObjSafe}, + effect::{Adapters, Effect, ObjSafe}, never::Never, protocol::{visitor::visit_value, DynVisitor}, WalkerTypes, @@ -43,15 +43,14 @@ impl<T> WalkerTypes for ValueWalker<T> { impl<'ctx, T: Send + Sync + 'static, E: Effect> crate::Walker<'ctx, E> for ValueWalker<T> { #[inline(always)] - fn walk<'a>( + fn walk<'b: 'c, 'c>( self, - visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> - where - Self: 'a, - { + visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Result<Self::Output, Self::Error>, E> { // Attempt to visit using the value protocol. - todo!() + visit_value::<_, E>(visitor, OwnedStatic(self.0)) + .map(|_| Ok(())) + .into() // E::map( // visit_value::<_, E>(visitor, OwnedStatic(self.0)), // |_| Ok(()), @@ -82,13 +81,10 @@ impl<'ctx, T: ?Sized + Send + Sync + 'static, E: Effect> crate::Walker<'ctx, E> for BorrowWalker<'ctx, T> { #[inline(always)] - fn walk<'a>( + fn walk<'b: 'c, 'c>( self, - visitor: DynVisitor<'a, 'ctx>, - ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> - where - Self: 'a, - { + visitor: DynVisitor<'b, 'ctx>, + ) -> ObjSafe<'c, Result<Self::Output, Self::Error>, E> { // Attempt to visit using the value protocol. todo!() // E::map(visit_value::<_, E>(visitor, BorrowedStatic(self.0)), |_| { diff --git a/tests/builder_struct.rs b/tests/builder_struct.rs index aabad24..8aca415 100644 --- a/tests/builder_struct.rs +++ b/tests/builder_struct.rs @@ -293,18 +293,15 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo pub mod demo { use crate::Walk; use macro_rules_attribute::derive; - use treaty::{ - effect::{Blocking}, - transform, Build, DefaultMode, - }; + use treaty::{effect::Blocking, transform, Build, DefaultMode}; - #[derive(Build!, Walk!, Debug)] + #[derive(Walk!, Debug)] pub struct X { pub a: bool, pub b: bool, } - #[derive(Build!, Walk!, Debug)] + #[derive(Build!, Debug)] pub struct Y { pub b: bool, pub a: bool, |