-rw-r--r--src/build/builders/core/struct.rs55
-rw-r--r--src/effect.rs364
-rw-r--r--src/lib.rs11
-rw-r--r--src/macros/build.rs24
-rw-r--r--src/protocol/visitor/recoverable.rs5
-rw-r--r--src/protocol/visitor/sequence.rs1
-rw-r--r--src/transform.rs23
-rw-r--r--src/walk.rs12
-rw-r--r--src/walk/walkers/core/key_value.rs32
-rw-r--r--src/walk/walkers/core/noop.rs9
-rw-r--r--src/walk/walkers/core/struct.rs73
-rw-r--r--src/walk/walkers/core/tag.rs9
-rw-r--r--src/walk/walkers/core/value.rs24
-rw-r--r--tests/builder_struct.rs9
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 {
diff --git a/src/lib.rs b/src/lib.rs
index 56a6063..6fd3a2a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,