rustc oom
| -rw-r--r-- | Cargo.lock | 126 | ||||
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | src/any.rs | 6 | ||||
| -rw-r--r-- | src/any/type_name_id.rs | 4 | ||||
| -rw-r--r-- | src/build.rs | 6 | ||||
| -rw-r--r-- | src/build/builders.rs | 4 | ||||
| -rw-r--r-- | src/build/builders/core/bool.rs | 20 | ||||
| -rw-r--r-- | src/build/builders/core/struct.rs | 161 | ||||
| -rw-r--r-- | src/effect.rs | 245 | ||||
| -rw-r--r-- | src/hkt.rs | 5 | ||||
| -rw-r--r-- | src/macros/build.rs | 2 | ||||
| -rw-r--r-- | src/protocol/visitor/recoverable.rs | 10 | ||||
| -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/tag.rs | 90 | ||||
| -rw-r--r-- | src/protocol/visitor/value.rs | 8 | ||||
| -rw-r--r-- | src/protocol/walker/hint.rs | 6 | ||||
| -rw-r--r-- | src/transform.rs | 29 | ||||
| -rw-r--r-- | src/walk.rs | 59 | ||||
| -rw-r--r-- | src/walk/walkers/core/key_value.rs | 113 | ||||
| -rw-r--r-- | src/walk/walkers/core/noop.rs | 6 | ||||
| -rw-r--r-- | src/walk/walkers/core/struct.rs | 546 | ||||
| -rw-r--r-- | src/walk/walkers/core/tag.rs | 67 | ||||
| -rw-r--r-- | src/walk/walkers/core/value.rs | 28 | ||||
| -rw-r--r-- | tests/builder_struct.rs | 304 |
25 files changed, 1125 insertions, 742 deletions
@@ -127,6 +127,95 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] name = "getrandom" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -317,12 +406,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -536,6 +651,15 @@ dependencies = [ ] [[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] name = "smallvec" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -615,8 +739,10 @@ dependencies = [ name = "treaty" version = "0.0.1" dependencies = [ + "futures", "macro_rules_attribute", "mockall", + "pin-project", "proptest", "serde_json", "tokio", @@ -10,6 +10,8 @@ readme = "README.md" # include = ["LICENSE-APACHE", "LICENSE-MIT", "README.md", "empty.rs"] [dependencies] +futures = "0.3.30" +pin-project = "1.1.5" # serde = { version = "1.0", default-features = false, optional = true } [features] @@ -180,6 +180,7 @@ impl<'b, 'ctx: 'b> dyn AnyTrait<'ctx> + Send + Sync + 'b { /// as it automatically downcasts the returned [`AnyTraitObject`]. /// /// If the returned [`AnyTraitObject`] is the wrong type, then a panic happens. + #[inline(always)] pub fn upcast<'a, Trait: ?Sized + TypeName::MemberType>( &'a self, ) -> Option<&'a TypeName::T<'a, 'ctx, Trait>> { @@ -201,6 +202,7 @@ impl<'b, 'ctx: 'b> dyn AnyTrait<'ctx> + Send + Sync + 'b { /// as it automatically downcasts the returned [`AnyTraitObject`]. /// /// If the returned [`AnyTraitObject`] is the wrong type, then a panic happens. + #[inline(always)] pub fn upcast_mut<'a, Trait: ?Sized + TypeName::MemberType>( &'a mut self, ) -> Option<&'a mut TypeName::T<'a, 'ctx, Trait>> { @@ -239,7 +241,7 @@ macro_rules! any_trait { impl<$lt $($generic)*> $crate::any::AnyTrait<$lt> for $name $(where $($bound)*)? { - #[inline] + #[inline(always)] fn upcast_to_id<'__>( &'__ self, id: $crate::any::TypeNameId @@ -260,7 +262,7 @@ macro_rules! any_trait { } } - #[inline] + #[inline(always)] fn upcast_to_id_mut<'__>( &'__ mut self, id: $crate::any::TypeNameId diff --git a/src/any/type_name_id.rs b/src/any/type_name_id.rs index 1e47f12..53d0945 100644 --- a/src/any/type_name_id.rs +++ b/src/any/type_name_id.rs @@ -21,6 +21,7 @@ pub struct TypeNameId { impl TypeNameId { /// Get the type ID from a [`TypeName::LowerType`] ([`WithContextLt`]) higher ranked type. + #[inline(always)] pub fn of<T: ?Sized + TypeName::MemberType>() -> Self { Self { name_id: TypeId::of::<T>(), @@ -31,6 +32,7 @@ impl TypeNameId { } /// Get the type ID from a lower type. + #[inline(always)] pub fn of_lower<'a, 'ctx: 'a, T: ?Sized + TypeName::LowerType<'a, 'ctx>>() -> Self { Self { name_id: TypeId::of::<TypeName::HigherRanked<'a, 'ctx, T>>(), @@ -41,6 +43,7 @@ impl TypeNameId { } /// Get the type ID of a lower type's value. + #[inline(always)] pub fn of_value<'a, 'ctx: 'a, T: ?Sized + TypeName::LowerType<'a, 'ctx>>(_: &T) -> Self { Self::of_lower::<'a, 'ctx, T>() } @@ -48,6 +51,7 @@ impl TypeNameId { /// Converts the type name ID to a normal [`TypeId`]. /// /// This is the [`TypeId`] of the `T` passed to [`Self::of`]. + #[inline(always)] pub fn into_type_id(self) -> TypeId { self.name_id } diff --git a/src/build.rs b/src/build.rs index f5db1d2..e1c62f7 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,7 +1,7 @@ pub mod builders; use crate::{ - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, protocol::DynVisitor, }; @@ -35,7 +35,7 @@ pub trait BuilderTypes { /// - Call [`Self::build()`] to finish building the value and get any errors /// that happened during filling it with data. pub trait Builder<'ctx, E: Effect>: BuilderTypes + Sized + Send + Sync { - fn from_seed<'a>(seed: Self::Seed) -> Future<'a, Self, E> + fn from_seed<'a>(seed: Self::Seed) -> ObjSafe<'a, Self, E> where Self: 'a; @@ -43,7 +43,7 @@ pub trait Builder<'ctx, E: Effect>: BuilderTypes + Sized + Send + Sync { /// /// If an error happened with the builder during the walk /// it will be reported here. - fn build<'a>(self) -> Future<'a, Result<Self::Value, Self::Error>, E> + fn build<'a>(self) -> ObjSafe<'a, Result<Self::Value, Self::Error>, E> where Self: 'a; diff --git a/src/build/builders.rs b/src/build/builders.rs index 1a19319..95697d4 100644 --- a/src/build/builders.rs +++ b/src/build/builders.rs @@ -3,5 +3,5 @@ pub mod core; // #[cfg(feature = "serde")] // pub mod serde; -#[cfg(feature = "std")] -pub mod debug; +// #[cfg(feature = "std")] +// pub mod debug; diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs index bc2706d..26ad20d 100644 --- a/src/build/builders/core/bool.rs +++ b/src/build/builders/core/bool.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use crate::{ any::OwnedStatic, any_trait, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, protocol::{ visitor::{Value, ValueProto, VisitResult}, DynVisitor, @@ -39,21 +39,23 @@ impl<E> crate::BuilderTypes for Builder<E> { } impl<'ctx, E: Effect> crate::Builder<'ctx, E> for Builder<E> { - #[inline] - fn build<'a>(self) -> Future<'a, Result<Self::Value, Self::Error>, E> + #[inline(always)] + fn build<'a>(self) -> ObjSafe<'a, Result<Self::Value, Self::Error>, E> where Self: 'a, { - E::wrap(core::future::ready(self.0.ok_or(Error::Incomplete))) + E::ready(self.0.ok_or(Error::Incomplete)).into() } - fn from_seed<'a>(_seed: Self::Seed) -> Future<'a, Self, E> + #[inline(always)] + fn from_seed<'a>(_seed: Self::Seed) -> ObjSafe<'a, Self, E> where Self: 'a, { - E::wrap(core::future::ready(Self(None, PhantomData))) + E::ready(Self(None, PhantomData)).into() } + #[inline(always)] fn as_visitor(&mut self) -> DynVisitor<'_, 'ctx> { DynVisitor(self) } @@ -66,15 +68,15 @@ any_trait! { } impl<'ctx, E: Effect> Value<'ctx, OwnedStatic<bool>, E> for Builder<E> { - #[inline] + #[inline(always)] fn visit<'a>( &'a mut self, OwnedStatic(value): OwnedStatic<bool>, - ) -> Future<'a, VisitResult<OwnedStatic<bool>>, E> + ) -> ObjSafe<'a, VisitResult<OwnedStatic<bool>>, E> where 'ctx: 'a, { self.0 = Some(value); - E::ready(Flow::Done.into()) + E::ready(Flow::Done.into()).into() } } diff --git a/src/build/builders/core/struct.rs b/src/build/builders/core/struct.rs index feada5d..fa22457 100644 --- a/src/build/builders/core/struct.rs +++ b/src/build/builders/core/struct.rs @@ -1,7 +1,7 @@ use crate::{ any::{OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, any_trait, - effect::{Effect, Future}, + effect::{Effect, ObjSafe, Adapters}, hkt::Marker, protocol::{ visitor::{ @@ -40,9 +40,9 @@ pub trait StructTypeInfo<'ctx, M, E: Effect>: 'static { type T: Send + Sync; - fn new_builders<'a>(seed: Self::Seed) -> Future<'a, Self::Builders, E>; + fn new_builders<'a>(seed: Self::Seed) -> ObjSafe<'a, Self::Builders, E>; - fn from_builders<'a>(builders: Self::Builders) -> Future<'a, Result<Self::T, Self::Error>, E>; + fn from_builders<'a>(builders: Self::Builders) -> ObjSafe<'a, Result<Self::T, Self::Error>, E>; fn as_visitor<'a>( marker: Self::FieldMarker, @@ -83,30 +83,30 @@ where I: StructTypeInfo<'ctx, M, E>, E: Effect, { - fn from_seed<'a>(seed: Self::Seed) -> Future<'a, Self, E> + fn from_seed<'a>(seed: Self::Seed) -> ObjSafe<'a, Self, E> where Self: 'a, { - E::wrap(async { + I::new_builders(seed).map(|builders| { Self { - builders: I::new_builders(seed).await, + builders, // Start in tuple mode until a struct or map tag is visited. mode: StructMode::Tuple, _generics: Default::default(), } - }) + }).into() } - fn build<'a>(self) -> Future<'a, Result<Self::Value, Self::Error>, E> + fn build<'a>(self) -> ObjSafe<'a, Result<Self::Value, Self::Error>, E> where Self: 'a, { - E::wrap(async { - match I::from_builders(self.builders).await { + I::from_builders(self.builders).map(|builders| { + match builders { Ok(value) => Ok(value), Err(err) => Err(StructError { error: err }), } - }) + }).into() } fn as_visitor(&mut self) -> DynVisitor<'_, 'ctx> { @@ -128,21 +128,24 @@ where I: StructTypeInfo<'ctx, M, E>, E: Effect, { + #[inline(always)] fn visit<'a>( &'a mut self, _kind: tags::Map, walker: DynWalkerObjSafe<'a, 'ctx, E>, - ) -> Future<'a, VisitResult<DynWalkerObjSafe<'a, 'ctx, E>>, E> { + ) -> ObjSafe<'a, VisitResult<DynWalkerObjSafe<'a, 'ctx, E>>, E> { // This signals to go into map mode for the sequence. self.mode = StructMode::Map; - E::wrap(async { + E::with(NoopVisitor::new(), |noop| { walker - .walk(DynVisitor(&mut NoopVisitor::new())) - .await - .to_continue() + .walk(DynVisitor(noop)) + .map(|x| { + x.to_continue() + .into() + }) .into() - }) + }).into() } } @@ -156,45 +159,46 @@ where fn visit<'a>( &'a mut self, scope: DynSequenceScope<'a, 'ctx, E>, - ) -> Future<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> { - match self.mode { - StructMode::Tuple => E::wrap(async { - let mut index = 0; - - // For each index based marker. - while let Some(marker) = I::marker_from_index(index) { - // Select the visitor for this field. - let visitor = I::as_visitor(marker, &mut self.builders); - - // Get the next value in the sequence. - match scope.next(visitor).await { - Flow::Continue => {} - Flow::Err => return VisitResult::Control(Flow::Err), - Flow::Done => break, - } - - // Move to the next field. - index += 1; - } - - VisitResult::Control(Flow::Done) - }), - StructMode::Map => E::wrap(async { - loop { - let mut visitor = FieldVisitor::<I, M, E> { - builders: &mut self.builders, - marker: None, - _marker: Default::default(), - }; - - match scope.next(DynVisitor(&mut visitor)).await { - Flow::Continue => {} - Flow::Err => return VisitResult::Control(Flow::Err), - Flow::Done => return VisitResult::Control(Flow::Done), - } - } - }), - } + ) -> ObjSafe<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> { + todo!() + // match self.mode { + // StructMode::Tuple => E::wrap(async { + // let mut index = 0; + // + // // For each index based marker. + // while let Some(marker) = I::marker_from_index(index) { + // // Select the visitor for this field. + // let visitor = I::as_visitor(marker, &mut self.builders); + // + // // Get the next value in the sequence. + // match scope.next(visitor).await { + // Flow::Continue => {} + // Flow::Err => return VisitResult::Control(Flow::Err), + // Flow::Done => break, + // } + // + // // Move to the next field. + // index += 1; + // } + // + // VisitResult::Control(Flow::Done) + // }), + // StructMode::Map => E::wrap(async { + // loop { + // let mut visitor = FieldVisitor::<I, M, E> { + // builders: &mut self.builders, + // marker: None, + // _marker: Default::default(), + // }; + // + // match scope.next(DynVisitor(&mut visitor)).await { + // Flow::Continue => {} + // Flow::Err => return VisitResult::Control(Flow::Err), + // Flow::Done => return VisitResult::Control(Flow::Done), + // } + // } + // }), + // } } } @@ -226,24 +230,26 @@ where E: Effect, I: StructTypeInfo<'ctx, M, E>, { + #[inline(always)] fn visit<'a>( &'a mut self, _key: tags::Key, walker: DynWalkerObjSafe<'a, 'ctx, E>, - ) -> Future<'a, VisitResult<DynWalkerObjSafe<'a, 'ctx, E>>, E> { - E::wrap(async { - let mut visitor = NameVisitor::<I, M, E> { - field_marker: None, - _marker: Default::default(), - }; - - let flow = walker.walk(DynVisitor(&mut visitor)).await; - - self.marker = visitor.field_marker; - - // We are expecting the value of the field to be given next. - flow.to_continue().into() - }) + ) -> ObjSafe<'a, VisitResult<DynWalkerObjSafe<'a, 'ctx, E>>, E> { + todo!() + // E::wrap(async { + // let mut visitor = NameVisitor::<I, M, E> { + // field_marker: None, + // _marker: Default::default(), + // }; + // + // let flow = walker.walk(DynVisitor(&mut visitor)).await; + // + // self.marker = visitor.field_marker; + // + // // We are expecting the value of the field to be given next. + // flow.to_continue().into() + // }) } } @@ -267,17 +273,18 @@ where E: Effect, I: StructTypeInfo<'ctx, M, E>, { + #[inline(always)] fn visit<'a>( &'a mut self, OwnedStatic(index): TypeName::T<'a, 'ctx, OwnedStatic<usize>>, - ) -> Future<'a, VisitResult<TypeName::T<'a, 'ctx, OwnedStatic<usize>>>, E> + ) -> ObjSafe<'a, VisitResult<TypeName::T<'a, 'ctx, OwnedStatic<usize>>>, E> where TypeName::T<'a, 'ctx, OwnedStatic<usize>>: Send + Sized, 'ctx: 'a, { self.field_marker = I::marker_from_index(index); - E::ready(VisitResult::Control(Flow::Done)) + E::ready(VisitResult::Control(Flow::Done)).into() } } @@ -286,17 +293,18 @@ where E: Effect, I: StructTypeInfo<'ctx, M, E>, { + #[inline(always)] fn visit<'a>( &'a mut self, TempBorrowedStatic(name): TypeName::T<'a, 'ctx, TempBorrowedStaticHrt<str>>, - ) -> Future<'a, VisitResult<TypeName::T<'a, 'ctx, TempBorrowedStaticHrt<str>>>, E> + ) -> ObjSafe<'a, VisitResult<TypeName::T<'a, 'ctx, TempBorrowedStaticHrt<str>>>, E> where TypeName::T<'a, 'ctx, TempBorrowedStaticHrt<str>>: Send + Sized, 'ctx: 'a, { self.field_marker = I::marker_from_name(name); - E::ready(VisitResult::Control(Flow::Done)) + E::ready(VisitResult::Control(Flow::Done)).into() } } @@ -305,16 +313,17 @@ where E: Effect, I: StructTypeInfo<'ctx, M, E>, { + #[inline(always)] fn visit<'a>( &'a mut self, OwnedStatic(name): TypeName::T<'a, 'ctx, OwnedStatic<&'static str>>, - ) -> Future<'a, VisitResult<TypeName::T<'a, 'ctx, OwnedStatic<&'static str>>>, E> + ) -> ObjSafe<'a, VisitResult<TypeName::T<'a, 'ctx, OwnedStatic<&'static str>>>, E> where TypeName::T<'a, 'ctx, TempBorrowedStaticHrt<str>>: Send + Sized, 'ctx: 'a, { self.field_marker = I::marker_from_name(name); - E::ready(VisitResult::Control(Flow::Done)) + E::ready(VisitResult::Control(Flow::Done)).into() } } diff --git a/src/effect.rs b/src/effect.rs index 3e3b8da..b0203bc 100644 --- a/src/effect.rs +++ b/src/effect.rs @@ -1,65 +1,237 @@ use core::{ + future::Future, marker::PhantomData, - pin::pin, + pin::{pin, Pin}, ptr, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }; +use futures::FutureExt; +use pin_project::pin_project; + use crate::{higher_ranked_trait, higher_ranked_type, hkt::Marker}; -higher_ranked_trait! { - pub type class SendFuture[Output] for<'a> { - type Bound = &'a Output; +// higher_ranked_trait! { +// pub type class Effective['lt, E] for<'a> { +// type Bound = &'a (&'lt (), T, E); +// +// type T: { Adapters<'a, Effect = E, T = T> + Sized + 'a } +// where { +// 'lt: 'a, +// T: 'a, +// E: Effect, +// }; +// +// type HigherRanked: {} where { +// E: Effect, +// }; +// } +// } - type T: { core::future::Future<Output = Output> + Sized + Send + 'a } - where { - Output: 'a - }; - type HigherRanked: {} where { - // Output: Send - }; - } +// fn do_thing<E: Effect>() -> ObjSafe<'static, i32, E> { +// E::ready(42).with(|x| { +// other::<E>(x).map(|x| x + 1).into() +// }).into() +// } +// +// fn other<E: Effect>(x: &i32) -> ObjSafe<'_, &i32, E> { +// E::ready(x).into() +// } + +// pub mod Effective { +// +// } +// +pub trait Adapters<'lt>: Into<<Self::Effect as Effect>::ObjSafe<'lt, Self::T>> + 'lt { + type Effect: Effect; + type T: 'lt; + + type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T>: Adapters<'a, Effect = Self::Effect, T = T> + where + 'lt: 'a; + + fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> + where + F: FnOnce(Self::T) -> R, + 'lt: 'a; } /// Trait for effects. -pub trait Effect: Send + Sync + 'static { - type Future<T: Send>: SendFuture::MemberType<T>; +pub trait Effect: Sized + Send + Sync + 'static { + type ObjSafe<'a, T: 'a>: Adapters<'a, Effect = Self, T = T>; - fn wrap<'a, F>(future: F) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>> + type Ready<'a, T: 'a>: Adapters<'a, Effect = Self, T = T>; + + fn ready<'a, T: 'a>(x: T) -> Self::Ready<'a, T>; + + type With<'a, T: 'a, R: 'a, F: 'a + FnOnce(&mut T) -> R>: Adapters<'a, Effect = Self, T = R>; + + fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> Self::With<'a, T, R::T, F> + where + R: Adapters<'a, Effect = Self>, + F: FnOnce(&mut T) -> R; +} + +pub type ObjSafe<'a, T, E> = <E as Effect>::ObjSafe<'a, T>; + +pub enum Blocking {} + +impl Effect for Blocking { + type ObjSafe<'a, T: 'a> = Value<T>; + + type Ready<'a, T: 'a> = Value<T>; + + fn ready<'a, T: 'a>(x: T) -> Self::Ready<'a, T> { + Value(x) + } + + type With<'a, T: 'a, R: 'a, F: 'a + FnOnce(&mut T) -> R> = Value<R>; + + fn with<'a, T: 'a, R: 'a, F: 'a>(x: T, f: F) -> Self::With<'a, T, R::T, F> + where + R: Adapters<'a, Effect = Self>, + F: FnOnce(&mut T) -> R { + let mut ctx = x; + Value(f(&mut ctx)) + } +} + +pub struct Value<T>(pub T); + +impl<'b, U: 'b> Adapters<'b> for Value<U> { + type Effect = Blocking; + + type T = U; + + type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = Value<T> where 'b: 'a; + + fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> where - F: core::future::Future + Send + 'a, - <F as core::future::Future>::Output: Send; + F: FnOnce(Self::T) -> R, + 'b: 'a, + { + Value(f(self.0)) + } +} - fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, T, Self::Future<T>>; +/* +pub enum Async {} - fn map<'a, T, U, F>( - future: SendFuture::T<'a, T, Self::Future<T>>, - func: F, - ) -> SendFuture::T<'a, U, Self::Future<U>> +impl Effect for Async { + type ObjSafe<'a, T: 'a> = BoxedFuture<'a, T>; + + type Ready<'a, T: 'a> = AsyncValue<T>; + + fn ready<'a, T: 'a>(x: T) -> Self::Ready<'a, T> { + AsyncValue(x) + } +} + +pub struct AsyncValue<T>(pub T); + +pub struct BoxedFuture<'a, T: 'a>(pub Pin<Box<dyn Future<Output = T> + 'a>>); + +impl<'b, U: 'b> Adapters<'b> for AsyncValue<U> { + type Effect = Async; + + type T = U; + + type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncValue<T> where 'b: 'a; + + fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> where - T: Send, - U: Send, - F: FnOnce(T) -> U + Send + 'a; + F: FnOnce(Self::T) -> R, + 'b: 'a, + { + AsyncValue(f(self.0)) + } +} - #[cfg(feature = "alloc")] - #[inline] - fn wrap_boxed<'a, F>( - future: core::pin::Pin<Box<F>>, - ) -> SendFuture::T<'a, F::Output, Self::Future<F::Output>> +impl<'b, U: 'b> Adapters<'b> for BoxedFuture<'b, U> { + type Effect = Async; + + type T = U; + + type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncMap<Self, F> where 'b: 'a; + + fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> where - F: core::future::Future + Send + 'a, - <F as core::future::Future>::Output: Send, + F: FnOnce(Self::T) -> R, + 'b: 'a, + { + AsyncMap { + map: futures::FutureExt::map(self, f) + } + } +} + +#[pin_project] +pub struct AsyncMap<Fut, F> { + #[pin] + map: futures::future::Map<Fut, F>, +} + +impl<'b, U: 'b, Fut0: 'b, F0: 'b> Adapters<'b> for AsyncMap<Fut0, F0> +where + Fut0: Future, + F0: FnOnce(Fut0::Output) -> U, +{ + type Effect = Async; + + type T = U; + + type Map<'a, T: 'a, F: 'a + FnOnce(Self::T) -> T> = AsyncMap<Self, F> where 'b: 'a; + + fn map<'a, R: 'a, F: 'a>(self, f: F) -> Self::Map<'a, R, F> + where + F: FnOnce(Self::T) -> R, + 'b: 'a, { - Self::wrap(future) + AsyncMap { + map: futures::FutureExt::map(self, f) + } + } +} + +impl<T, Fut, F> Future for AsyncMap<Fut, F> +where + Fut: Future, + F: FnOnce(Fut::Output) -> T, +{ + type Output = T; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + let this = self.project(); + this.map.poll(cx) + } +} + +impl<'a, T> Future for BoxedFuture<'a, T> { + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + self.0.poll_unpin(cx) } } -pub type Future<'a, T, E> = SendFuture::T<'a, T, <E as Effect>::Future<T>>; +impl<'a, T, Fut: 'a, F: 'a> From<AsyncMap<Fut, F>> for BoxedFuture<'a, T> +where + Fut: Future, + F: FnOnce(Fut::Output) -> T, +{ + fn from(value: AsyncMap<Fut, F>) -> Self { + BoxedFuture(Box::pin(value.map)) + } +} -pub struct Blocking<B = Spin> { - _marker: PhantomData<fn() -> B>, +impl<'a, T: 'a> From<AsyncValue<T>> for BoxedFuture<'a, T> { + fn from(value: AsyncValue<T>) -> Self { + BoxedFuture(Box::pin(futures::future::ready(value.0))) + } } +*/ +/* pub trait ReadyValue: core::future::Future { fn value(self) -> Self::Output; } @@ -272,3 +444,4 @@ impl Effect for Async { sealed::BoxedFuture::Box(future) } } +*/ @@ -62,6 +62,9 @@ macro_rules! higher_ranked_trait { $vis mod $name { #![allow(non_snake_case)] + #[allow(unused)] + use super::*; + pub trait LowerForLt<$($lt,)+ $($($generic)*,)? B> where $($($lower_where)*)? @@ -87,7 +90,7 @@ macro_rules! higher_ranked_trait { impl<$($($generic)*,)? __: ?Sized> MemberType$(<$($generic)*>)? for __ where - __: for<$($lt,)+> LowerForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>> + $($higher)? + __: for<$($lt,)+> LowerForLt<$($lt,)+ $($($generic)*,)? Bound<$($lt,)+ $($($generic)*)?>> + $($higher)?, $($($higher_where)*)? {} diff --git a/src/macros/build.rs b/src/macros/build.rs index 9d37bf6..158a9dc 100644 --- a/src/macros/build.rs +++ b/src/macros/build.rs @@ -1,5 +1,5 @@ use crate::{ - effect::{Blocking, ReadyValue}, + effect::{Blocking}, transform, DefaultMode, }; diff --git a/src/protocol/visitor/recoverable.rs b/src/protocol/visitor/recoverable.rs index b0d14de..e64820a 100644 --- a/src/protocol/visitor/recoverable.rs +++ b/src/protocol/visitor/recoverable.rs @@ -1,6 +1,6 @@ use crate::{ any::TypeName, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, higher_ranked_type, hkt::Marker, protocol::{ @@ -16,7 +16,7 @@ pub trait Recoverable<'ctx, E: Effect> { fn visit<'a>( &'a mut self, scope: DynRecoverableScope<'a, 'ctx, E>, - ) -> Future<'a, VisitResult<DynRecoverableScope<'a, 'ctx, E>>, E>; + ) -> ObjSafe<'a, VisitResult<DynRecoverableScope<'a, 'ctx, E>>, E>; } pub struct RecoverableProto<E: Effect>(Marker<E>); @@ -38,7 +38,7 @@ higher_ranked_type! { } pub trait RecoverableScope<'ctx, E: Effect> { - fn new_walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Status, E>; + fn new_walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Status, E>; } pub type DynRecoverableScope<'a, 'ctx, E> = @@ -67,12 +67,12 @@ impl<E: Effect> HintMeta for RecoverableProto<E> { pub fn visit_recoverable<'a, 'ctx, E: Effect>( visitor: DynVisitor<'a, 'ctx>, scope: DynRecoverableScope<'a, 'ctx, E>, -) -> Future<'a, VisitResult<DynRecoverableScope<'a, 'ctx, E>>, E> { +) -> ObjSafe<'a, VisitResult<DynRecoverableScope<'a, 'ctx, E>>, E> { if let Some(object) = visitor.0.upcast_mut::<RecoverableProto<E>>() { // Allow the visitor to give a hint if it wants. object.visit(scope) } else { // If the visitor doesn't support request hint then we continue. - E::ready(VisitResult::Skipped(scope)) + E::ready(VisitResult::Skipped(scope)).into() } } diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs index 1e699a1..e8c4d6d 100644 --- a/src/protocol/visitor/request_hint.rs +++ b/src/protocol/visitor/request_hint.rs @@ -1,6 +1,6 @@ use crate::{ any::TypeName, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, higher_ranked_type, hkt::Marker, protocol::{DynVisitor, DynWalker}, @@ -17,7 +17,7 @@ pub trait RequestHint<'ctx, E: Effect> { fn request_hint<'a>( &'a mut self, walker: DynWalker<'a, 'ctx>, - ) -> Future<'a, VisitResult<DynWalker<'a, 'ctx>>, E>; + ) -> ObjSafe<'a, VisitResult<DynWalker<'a, 'ctx>>, E>; } pub struct RequestHintProto<E: Effect>(Marker<E>); @@ -48,12 +48,12 @@ higher_ranked_type! { pub fn visit_request_hint<'a, 'ctx, E: Effect>( visitor: DynVisitor<'a, 'ctx>, walker: DynWalker<'a, 'ctx>, -) -> Future<'a, VisitResult<DynWalker<'a, 'ctx>>, E> { +) -> ObjSafe<'a, VisitResult<DynWalker<'a, 'ctx>>, E> { if let Some(object) = visitor.0.upcast_mut::<RequestHintProto<E>>() { // Allow the visitor to give a hint if it wants. object.request_hint(walker) } else { // If the visitor doesn't support request hint then we continue. - E::ready(VisitResult::Skipped(walker)) + E::ready(VisitResult::Skipped(walker)).into() } } diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs index ef0c5e9..f367ae2 100644 --- a/src/protocol/visitor/sequence.rs +++ b/src/protocol/visitor/sequence.rs @@ -1,6 +1,6 @@ use crate::{ any::TypeName, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, higher_ranked_type, hkt::Marker, protocol::{ @@ -20,7 +20,7 @@ pub trait Sequence<'ctx, E: Effect> { fn visit<'a>( &'a mut self, scope: DynSequenceScope<'a, 'ctx, E>, - ) -> Future<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E>; + ) -> ObjSafe<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E>; } pub struct SequenceProto<E: Effect>(Marker<E>); @@ -42,9 +42,9 @@ higher_ranked_type! { } pub trait SequenceScope<'ctx, E: Effect> { - fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E>; + fn size_hint(&mut self) -> ObjSafe<'_, (usize, Option<usize>), E>; - fn next<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Flow, E>; + fn next<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E>; } pub type DynSequenceScope<'a, 'ctx, E> = &'a mut (dyn SequenceScope<'ctx, E> + Send + Sync + 'a); @@ -89,12 +89,12 @@ impl<E: Effect> HintMeta for SequenceProto<E> { pub fn visit_sequence<'a, 'ctx, E: Effect>( visitor: DynVisitor<'a, 'ctx>, scope: DynSequenceScope<'a, 'ctx, E>, -) -> Future<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> { +) -> ObjSafe<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> { if let Some(object) = visitor.0.upcast_mut::<SequenceProto<E>>() { // Allow the visitor to give a hint if it wants. object.visit(scope) } else { // If the visitor doesn't support request hint then we continue. - E::ready(VisitResult::Skipped(scope)) + E::ready(VisitResult::Skipped(scope)).into() } } diff --git a/src/protocol/visitor/tag.rs b/src/protocol/visitor/tag.rs index e90dea6..2c947b5 100644 --- a/src/protocol/visitor/tag.rs +++ b/src/protocol/visitor/tag.rs @@ -1,6 +1,6 @@ use crate::{ any::TypeName, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, higher_ranked_type, hkt::Marker, protocol::{ @@ -49,7 +49,7 @@ pub trait Tag<'ctx, K: TagKind, E: Effect> { &'a mut self, kind: K, walker: DynWalkerObjSafe<'a, 'ctx, E>, - ) -> Future<'a, VisitResult<DynWalkerObjSafe<'a, 'ctx, E>>, E>; + ) -> ObjSafe<'a, VisitResult<DynWalkerObjSafe<'a, 'ctx, E>>, E>; } pub struct TagProto<K: TagKind, E: Effect>(Marker<(K, E)>); @@ -169,55 +169,57 @@ pub fn visit_tag<'a, 'ctx: 'a, K: TagKind, E: Effect, W: crate::Walker<'ctx, E> kind: K, mut visitor: DynVisitor<'a, 'ctx>, walker: W, -) -> Future<'a, Result<VisitResult<W>, TagError<W::Error>>, E> +) -> ObjSafe<'a, Result<VisitResult<W>, TagError<W::Error>>, E> where W: WalkerTypes, { // Wrap the walker to allow it to be passed to a dyn walker argument. let mut walker = DynWalkerAdapter::new(walker); - - E::wrap(async move { - let result = if let Some(object) = visitor.upcast_mut::<TagProto<K, E>>() { - // The visitor knows about this tag. - - // Visit the tag. - object.visit(kind, &mut walker).await - } else if core::any::TypeId::of::<TagDyn>() != core::any::TypeId::of::<K>() { - // Try the dynamic form if we didn't already. - if let Some(object) = visitor.upcast_mut::<TagProto<TagDyn, E>>() { - // The visitor can handle dynamic tags. - // If the visitor can't handle the tag kind then it can call .skip on the walker - // to disable the error for not walking it. - - // Visit the tag. - object.visit(TagDyn(kind.symbol()), &mut walker).await - } else { - let walker: W = walker - .into_innter() - .map_err(|err| map_walker_err(kind, err))?; - return Ok(VisitResult::Skipped(walker)); - } - } else { - let walker: W = walker - .into_innter() - .map_err(|err| map_walker_err(kind, err))?; - return Ok(VisitResult::Skipped(walker)); - }; - - match result { - // The walker was skipped. - VisitResult::Skipped(_) => match walker.into_innter() { - Ok(walker) => Ok(VisitResult::Skipped(walker)), - Err(err) => Err(map_walker_err(kind, err)), - }, - VisitResult::Control(flow) => match walker.finish() { - Ok(_) => Ok(VisitResult::Control(flow)), - Err(err) => Err(map_walker_err(kind, err)), - }, - } - }) + todo!() + + // E::wrap(async move { + // let result = if let Some(object) = visitor.upcast_mut::<TagProto<K, E>>() { + // // The visitor knows about this tag. + // + // // Visit the tag. + // object.visit(kind, &mut walker).await + // } else if core::any::TypeId::of::<TagDyn>() != core::any::TypeId::of::<K>() { + // // Try the dynamic form if we didn't already. + // if let Some(object) = visitor.upcast_mut::<TagProto<TagDyn, E>>() { + // // The visitor can handle dynamic tags. + // // If the visitor can't handle the tag kind then it can call .skip on the walker + // // to disable the error for not walking it. + // + // // Visit the tag. + // object.visit(TagDyn(kind.symbol()), &mut walker).await + // } else { + // let walker: W = walker + // .into_innter() + // .map_err(|err| map_walker_err(kind, err))?; + // return Ok(VisitResult::Skipped(walker)); + // } + // } else { + // let walker: W = walker + // .into_innter() + // .map_err(|err| map_walker_err(kind, err))?; + // return Ok(VisitResult::Skipped(walker)); + // }; + // + // match result { + // // The walker was skipped. + // VisitResult::Skipped(_) => match walker.into_innter() { + // Ok(walker) => Ok(VisitResult::Skipped(walker)), + // Err(err) => Err(map_walker_err(kind, err)), + // }, + // VisitResult::Control(flow) => match walker.finish() { + // Ok(_) => Ok(VisitResult::Control(flow)), + // Err(err) => Err(map_walker_err(kind, err)), + // }, + // } + // }) } +#[inline(always)] fn map_walker_err<K: TagKind, W: WalkerTypes>( kind: K, err: DynWalkerError<W>, diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs index e549935..9b4c65e 100644 --- a/src/protocol/visitor/value.rs +++ b/src/protocol/visitor/value.rs @@ -4,7 +4,7 @@ use crate::{ any::TypeName, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, higher_ranked_type, hkt::Marker, protocol::{ @@ -31,7 +31,7 @@ pub trait Value<'ctx, T: ?Sized + TypeName::MemberType, E: Effect> { fn visit<'a>( &'a mut self, value: TypeName::T<'a, 'ctx, T>, - ) -> Future<'a, VisitResult<TypeName::T<'a, 'ctx, T>>, E> + ) -> ObjSafe<'a, VisitResult<TypeName::T<'a, 'ctx, T>>, E> where TypeName::T<'a, 'ctx, T>: Send + Sized, 'ctx: 'a; @@ -96,7 +96,7 @@ impl<T: TypeName::MemberType, E: Effect> HintMeta for ValueProto<T, E> { pub fn visit_value<'a, 'ctx, T: Send + TypeName::LowerType<'a, 'ctx>, E: Effect>( visitor: DynVisitor<'a, 'ctx>, value: T, -) -> Future<'a, VisitResult<T>, E> +) -> ObjSafe<'a, VisitResult<T>, E> where TypeName::HigherRanked<'a, 'ctx, T>: TypeName::MemberType, { @@ -108,6 +108,6 @@ where object.visit(value) } else { // If the visitor doesn't support request hint then we continue. - E::ready(VisitResult::Skipped(value)) + E::ready(VisitResult::Skipped(value)).into() } } diff --git a/src/protocol/walker/hint.rs b/src/protocol/walker/hint.rs index 9253264..a580ab0 100644 --- a/src/protocol/walker/hint.rs +++ b/src/protocol/walker/hint.rs @@ -6,7 +6,7 @@ use crate::{ any::TypeName, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, higher_ranked_trait, higher_ranked_type, hkt::Marker, protocol::DynVisitor, @@ -58,13 +58,13 @@ pub trait Hint<'ctx, Protocol: ?Sized + HintMeta> { &'a mut self, visitor: DynVisitor<'a, 'ctx>, hint: MetaHint<'a, 'ctx, Protocol>, - ) -> Future<'a, Flow, Protocol::Effect>; + ) -> ObjSafe<'a, Flow, Protocol::Effect>; /// Ask the walker for information about it's support of the protocol. fn known<'a>( &'a mut self, hint: &'a MetaHint<'a, 'ctx, Protocol>, - ) -> Future<'a, Result<MetaKnown<'a, 'ctx, Protocol>, ()>, Protocol::Effect>; + ) -> ObjSafe<'a, Result<MetaKnown<'a, 'ctx, Protocol>, ()>, Protocol::Effect>; } pub struct HintProto<Protocol: ?Sized>(Marker<Protocol>); diff --git a/src/transform.rs b/src/transform.rs index 9e5a215..91129c7 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -1,6 +1,6 @@ use crate::{ build::Builder, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, hkt::Marker, Walk, Walker, WalkerTypes, }; @@ -10,19 +10,20 @@ use crate::{ pub fn transform<'a, 'ctx, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect>( seed: B::Seed, walker: W, -) -> Future<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> { - E::wrap(async { - // Create builder from seed value; - let mut builder = B::from_seed(seed).await; - - // Walk the walker with the builder as the visitor. - let walker_result = walker.walk(builder.as_visitor()).await; - - // Finish building the value. - let builder_result = builder.build().await; - - (builder_result, walker_result) - }) +) -> ObjSafe<'a, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> { + todo!() + // E::wrap(async { + // // Create builder from seed value; + // let mut builder = B::from_seed(seed).await; + // + // // Walk the walker with the builder as the visitor. + // let walker_result = walker.walk(builder.as_visitor()).await; + // + // // Finish building the value. + // let builder_result = builder.build().await; + // + // (builder_result, walker_result) + // }) } /// For use in a lens. diff --git a/src/walk.rs b/src/walk.rs index 4c2042c..a7ace88 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,7 +1,7 @@ pub mod walkers; use crate::{ - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, protocol::DynVisitor, Flow, }; @@ -40,13 +40,13 @@ pub trait Walker<'ctx, E: Effect>: WalkerTypes + Send + Sync { fn walk<'a>( self, visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a; } pub trait WalkerObjSafe<'ctx, E: Effect>: Send { - fn walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Flow, E> + fn walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E> where Self: 'a; } @@ -77,12 +77,14 @@ pub struct DynWalkerAdapter<W: WalkerTypes> { } impl<W: WalkerTypes> DynWalkerAdapter<W> { + #[inline(always)] pub fn new(walker: W) -> Self { Self { state: DynWalkerState::Pending(walker), } } + #[inline(always)] pub fn finish(self) -> Result<W::Output, DynWalkerError<W>> { match self.state { DynWalkerState::Walking => Err(DynWalkerError::WalkNeverFinished), @@ -92,6 +94,7 @@ impl<W: WalkerTypes> DynWalkerAdapter<W> { } } + #[inline(always)] pub fn into_innter(self) -> Result<W, DynWalkerError<W>> { match self.state { DynWalkerState::Walking => Err(DynWalkerError::WalkNeverFinished), @@ -103,32 +106,34 @@ impl<W: WalkerTypes> DynWalkerAdapter<W> { } impl<'ctx, W: Walker<'ctx, E>, E: Effect> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<W> { - fn walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Flow, E> + #[inline(always)] + fn walk<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E> where Self: 'a, { - E::wrap(async { - if let DynWalkerState::Pending(walker) = - core::mem::replace(&mut self.state, DynWalkerState::Walking) - { - // Walk the walker. - match walker.walk(visitor).await { - Ok(value) => { - self.state = DynWalkerState::Done(value); - Flow::Done - } - Err(err) => { - self.state = DynWalkerState::Err(err); - - // Signal that control flow should stop as soon as possible as we - // are in an error state. - Flow::Err - } - } - } else { - // Can't do anything if the walker has already been walked. - Flow::Done - } - }) + todo!() + // E::wrap(async { + // if let DynWalkerState::Pending(walker) = + // core::mem::replace(&mut self.state, DynWalkerState::Walking) + // { + // // Walk the walker. + // match walker.walk(visitor).await { + // Ok(value) => { + // self.state = DynWalkerState::Done(value); + // Flow::Done + // } + // Err(err) => { + // self.state = DynWalkerState::Err(err); + // + // // Signal that control flow should stop as soon as possible as we + // // are in an error state. + // Flow::Err + // } + // } + // } else { + // // Can't do anything if the walker has already been walked. + // Flow::Done + // } + // }) } } diff --git a/src/walk/walkers/core/key_value.rs b/src/walk/walkers/core/key_value.rs index 8e14a1c..987d3bf 100644 --- a/src/walk/walkers/core/key_value.rs +++ b/src/walk/walkers/core/key_value.rs @@ -1,5 +1,5 @@ use crate::{ - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, never::Never, protocol::{ visitor::{visit_tag, TagConst, TagError, TagKind, VisitResult}, @@ -16,6 +16,7 @@ pub struct KeyValueWalker<T, K, V> { } impl<T, K, V> KeyValueWalker<T, K, V> { + #[inline(always)] pub fn new(tag: T, key_walker: K, value_walker: V) -> Self { Self { key_walker, @@ -53,65 +54,67 @@ where K: crate::Walker<'ctx, E>, V: crate::Walker<'ctx, E>, { + #[inline(always)] fn walk<'a>( self, mut visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { - E::wrap(async move { - match visit_tag::<T, E, _>(self.tag, visitor.cast(), NoopWalker::new()).await { - Ok(VisitResult::Skipped(_)) => { - match visit_tag::<TagConst<{ TAG_KEY_VALUE.to_int() }>, E, _>( - TagConst, - visitor.cast(), - NoopWalker::new(), - ) - .await - { - Ok(VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(_flow)) => return Ok(()), - Err(_) => todo!(), - } - } - Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(_flow)) => todo!(), - Err(_) => todo!(), - } - - match visit_tag::<TagConst<{ TAG_KEY.to_int() }>, E, _>( - TagConst, - visitor.cast(), - self.key_walker, - ) - .await - { - Ok(VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(_flow)) => return Ok(()), - Err(_) => todo!(), - } - - match visit_tag::<TagConst<{ TAG_VALUE.to_int() }>, E, _>( - TagConst, - visitor.cast(), - self.value_walker, - ) - .await - { - Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Skipped(value_walker)) => { - // Fallback to just walking the value. - match value_walker.walk(visitor).await { - Ok(_) => {} - Err(_err) => todo!(), - } - } - Ok(VisitResult::Control(_flow)) => todo!(), - Err(_) => todo!(), - } - - Ok(()) - }) + todo!() + // E::wrap(async move { + // match visit_tag::<T, E, _>(self.tag, visitor.cast(), NoopWalker::new()).await { + // Ok(VisitResult::Skipped(_)) => { + // match visit_tag::<TagConst<{ TAG_KEY_VALUE.to_int() }>, E, _>( + // TagConst, + // visitor.cast(), + // NoopWalker::new(), + // ) + // .await + // { + // Ok(VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue)) => {} + // Ok(VisitResult::Control(_flow)) => return Ok(()), + // Err(_) => todo!(), + // } + // } + // Ok(VisitResult::Control(Flow::Continue)) => {} + // Ok(VisitResult::Control(_flow)) => todo!(), + // Err(_) => todo!(), + // } + // + // match visit_tag::<TagConst<{ TAG_KEY.to_int() }>, E, _>( + // TagConst, + // visitor.cast(), + // self.key_walker, + // ) + // .await + // { + // Ok(VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue)) => {} + // Ok(VisitResult::Control(_flow)) => return Ok(()), + // Err(_) => todo!(), + // } + // + // match visit_tag::<TagConst<{ TAG_VALUE.to_int() }>, E, _>( + // TagConst, + // visitor.cast(), + // self.value_walker, + // ) + // .await + // { + // Ok(VisitResult::Control(Flow::Continue)) => {} + // Ok(VisitResult::Skipped(value_walker)) => { + // // Fallback to just walking the value. + // match value_walker.walk(visitor).await { + // Ok(_) => {} + // Err(_err) => todo!(), + // } + // } + // Ok(VisitResult::Control(_flow)) => todo!(), + // Err(_) => todo!(), + // } + // + // Ok(()) + // }) } } diff --git a/src/walk/walkers/core/noop.rs b/src/walk/walkers/core/noop.rs index 7468016..4a7f255 100644 --- a/src/walk/walkers/core/noop.rs +++ b/src/walk/walkers/core/noop.rs @@ -1,5 +1,5 @@ use crate::{ - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, never::Never, protocol::DynVisitor, WalkerTypes, @@ -28,10 +28,10 @@ impl<'ctx, E: Effect> crate::Walker<'ctx, E> for NoopWalker { fn walk<'a>( self, _visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { - E::ready(Ok(())) + E::ready(Ok(())).into() } } diff --git a/src/walk/walkers/core/struct.rs b/src/walk/walkers/core/struct.rs index 9e301e8..81e6950 100644 --- a/src/walk/walkers/core/struct.rs +++ b/src/walk/walkers/core/struct.rs @@ -3,7 +3,7 @@ use core::any::TypeId; use crate::{ any::{AnyTrait, BorrowedStatic, BorrowedStaticHrt}, any_trait, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, hkt::Marker, never::Never, protocol::{ @@ -65,7 +65,7 @@ pub trait StructTypeInfo<'ctx, M>: 'static { index: usize, value: &'ctx Self::T, visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Flow, Self::FieldError>, E>; + ) -> ObjSafe<'a, Result<Flow, Self::FieldError>, E>; } #[derive(Debug, PartialEq, Clone, Copy)] @@ -121,23 +121,25 @@ where I: StructTypeInfo<'ctx, M, S = S>, Self: AnyTrait<'ctx> + RecoverableScope<'ctx, E>, { + #[inline(always)] fn walk<'a>( mut self, mut visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { - E::wrap(async move { - // Use the recoverable walk to not duplicate the code. - let _ = RecoverableScope::<'ctx, E>::new_walk(&mut self, visitor.cast()).await; - - // Get the error if there was one. - match self.error { - Some(err) => Err(StructWalkError { kind: err }), - None => Ok(()), - } - }) + todo!() + // E::wrap(async move { + // // Use the recoverable walk to not duplicate the code. + // let _ = RecoverableScope::<'ctx, E>::new_walk(&mut self, visitor.cast()).await; + // + // // Get the error if there was one. + // match self.error { + // Some(err) => Err(StructWalkError { kind: err }), + // None => Ok(()), + // } + // }) } } @@ -164,25 +166,28 @@ where I: StructTypeInfo<'ctx, M, S = S>, Self: AnyTrait<'ctx> + RecoverableScope<'ctx, E>, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: <RecoverableProto<E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { - E::map( - visit_recoverable::<E>(visitor, self), - |status| match status { - VisitResult::Skipped(_) => Flow::Continue, - VisitResult::Control(flow) => flow, - }, - ) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_recoverable::<E>(visitor, self), + // |status| match status { + // VisitResult::Skipped(_) => Flow::Continue, + // VisitResult::Control(flow) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a <RecoverableProto<E> as HintMeta>::Hint, - ) -> Future<'a, Result<MetaKnown<'a, 'ctx, RecoverableProto<E>>, ()>, E> { - E::ready(Ok(RecoverableKnown)) + ) -> ObjSafe<'a, Result<MetaKnown<'a, 'ctx, RecoverableProto<E>>, ()>, E> { + E::ready(Ok(RecoverableKnown)).into() } } @@ -192,39 +197,42 @@ where E: Effect, I: StructTypeInfo<'ctx, M, S = S>, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: MetaHint<'a, 'ctx, TagProto<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>>, - ) -> Future<'a, Flow, E> { - E::map( - visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>( - TagConst, - visitor, - StaticSliceWalker::<_, ValueWalker<&'static str>>::new(I::FIELDS), - ), - |status| match status { - Err(err) => { - self.error = Some(StructWalkErrorKind::FieldTag(err)); - Flow::Err - } - Ok(VisitResult::Skipped(_)) => Flow::Continue, - Ok(VisitResult::Control(flow)) => flow, - }, - ) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>( + // TagConst, + // visitor, + // StaticSliceWalker::<_, ValueWalker<&'static str>>::new(I::FIELDS), + // ), + // |status| match status { + // Err(err) => { + // self.error = Some(StructWalkErrorKind::FieldTag(err)); + // Flow::Err + // } + // Ok(VisitResult::Skipped(_)) => Flow::Continue, + // Ok(VisitResult::Control(flow)) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a MetaHint<'a, 'ctx, TagProto<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>>, - ) -> Future< + ) -> ObjSafe< 'a, Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>>, ()>, E, > { E::ready(Ok(TagKnown { kind_available: Some(true), - })) + })).into() } } @@ -234,39 +242,42 @@ where E: Effect, I: StructTypeInfo<'ctx, M, S = S>, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: <TagProto<TagConst<{ TAG_TYPE_NAME.to_int() }>, E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { - E::map( - visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>( - TagConst, - visitor, - ValueWalker::new(I::NAME), - ), - |status| match status { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - Flow::Err - } - Ok(VisitResult::Skipped(_)) => Flow::Continue, - Ok(VisitResult::Control(flow)) => flow, - }, - ) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>( + // TagConst, + // visitor, + // ValueWalker::new(I::NAME), + // ), + // |status| match status { + // Err(err) => { + // self.error = Some(StructWalkErrorKind::Tag(err)); + // Flow::Err + // } + // Ok(VisitResult::Skipped(_)) => Flow::Continue, + // Ok(VisitResult::Control(flow)) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a <TagProto<TagConst<{ TAG_TYPE_NAME.to_int() }>, E> as HintMeta>::Hint, - ) -> Future< + ) -> ObjSafe< 'a, Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_TYPE_NAME.to_int() }>, E>>, ()>, E, > { E::ready(Ok(TagKnown { kind_available: Some(true), - })) + })).into() } } @@ -276,32 +287,35 @@ where E: Effect, I: StructTypeInfo<'ctx, M, S = S>, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: <TagProto<TagConst<{ TAG_MAP.to_int() }>, E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { - E::map( - visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()), - |status| match status { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - Flow::Err - } - Ok(VisitResult::Skipped(_)) => Flow::Continue, - Ok(VisitResult::Control(flow)) => flow, - }, - ) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()), + // |status| match status { + // Err(err) => { + // self.error = Some(StructWalkErrorKind::Tag(err)); + // Flow::Err + // } + // Ok(VisitResult::Skipped(_)) => Flow::Continue, + // Ok(VisitResult::Control(flow)) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a <TagProto<TagConst<{ TAG_MAP.to_int() }>, E> as HintMeta>::Hint, - ) -> Future<'a, Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_MAP.to_int() }>, E>>, ()>, E> + ) -> ObjSafe<'a, Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_MAP.to_int() }>, E>>, ()>, E> { E::ready(Ok(TagKnown { kind_available: Some(true), - })) + })).into() } } @@ -311,39 +325,42 @@ where E: Effect, I: StructTypeInfo<'ctx, M, S = S>, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: <TagProto<TagConst<{ TAG_STRUCT.to_int() }>, E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { - E::map( - visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( - TagConst, - visitor, - NoopWalker::new(), - ), - |status| match status { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - Flow::Err - } - Ok(VisitResult::Skipped(_)) => Flow::Continue, - Ok(VisitResult::Control(flow)) => flow, - }, - ) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( + // TagConst, + // visitor, + // NoopWalker::new(), + // ), + // |status| match status { + // Err(err) => { + // self.error = Some(StructWalkErrorKind::Tag(err)); + // Flow::Err + // } + // Ok(VisitResult::Skipped(_)) => Flow::Continue, + // Ok(VisitResult::Control(flow)) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a <TagProto<TagConst<{ TAG_STRUCT.to_int() }>, E> as HintMeta>::Hint, - ) -> Future< + ) -> ObjSafe< 'a, Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_STRUCT.to_int() }>, E>>, ()>, E, > { E::ready(Ok(TagKnown { kind_available: Some(true), - })) + })).into() } } @@ -354,39 +371,42 @@ where I: StructTypeInfo<'ctx, M, S = StaticType>, I::T: 'static, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: <TagProto<TagConst<{ TAG_TYPE_ID.to_int() }>, E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { - E::map( - visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( - TagConst, - visitor, - ValueWalker::new(TypeId::of::<I::T>()), - ), - |status| match status { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - Flow::Err - } - Ok(VisitResult::Skipped(_)) => Flow::Continue, - Ok(VisitResult::Control(flow)) => flow, - }, - ) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( + // TagConst, + // visitor, + // ValueWalker::new(TypeId::of::<I::T>()), + // ), + // |status| match status { + // Err(err) => { + // self.error = Some(StructWalkErrorKind::Tag(err)); + // Flow::Err + // } + // Ok(VisitResult::Skipped(_)) => Flow::Continue, + // Ok(VisitResult::Control(flow)) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a <TagProto<TagConst<{ TAG_TYPE_ID.to_int() }>, E> as HintMeta>::Hint, - ) -> Future< + ) -> ObjSafe< 'a, Result<MetaKnown<'a, 'ctx, TagProto<TagConst<{ TAG_TYPE_ID.to_int() }>, E>>, ()>, E, > { E::ready(Ok(TagKnown { kind_available: Some(true), - })) + })).into() } } @@ -396,11 +416,12 @@ where I: StructTypeInfo<'ctx, M, S = StaticType>, I::T: 'static, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, hint: <TagProto<TagDyn, E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { + ) -> ObjSafe<'a, Flow, E> { match hint.kind.0 { crate::TAG_TYPE_ID => { Hint::<'ctx, TagProto<TagConst<{ TAG_TYPE_ID.to_int() }>, E>>::hint( @@ -432,14 +453,15 @@ where 'ctx, TagProto<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>, >::hint(self, visitor, TagHint { kind: TagConst }), - _ => E::ready(Flow::Continue), + _ => E::ready(Flow::Continue).into(), } } + #[inline(always)] fn known<'a>( &'a mut self, hint: &'a <TagProto<TagDyn, E> as HintMeta>::Hint, - ) -> Future<'a, Result<MetaKnown<'a, 'ctx, TagProto<TagDyn, E>>, ()>, E> { + ) -> ObjSafe<'a, Result<MetaKnown<'a, 'ctx, TagProto<TagDyn, E>>, ()>, E> { E::ready(match hint.kind { TagDyn(crate::TAG_TYPE_ID) | TagDyn(crate::TAG_STRUCT) => Ok(TagKnown { kind_available: Some(true), @@ -447,7 +469,7 @@ where _ => Ok(TagKnown { kind_available: Some(false), }), - }) + }).into() } } @@ -458,21 +480,24 @@ where I: StructTypeInfo<'ctx, M, S = StaticType>, I::T: 'static, { - fn hint<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: ()) -> Future<'a, Flow, E> { - E::map( - visit_value::<_, E>(visitor, BorrowedStatic(self.value)), - |status| match status { - VisitResult::Skipped(_) => Flow::Continue, - VisitResult::Control(flow) => flow, - }, - ) + #[inline(always)] + fn hint<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: ()) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map( + // visit_value::<_, E>(visitor, BorrowedStatic(self.value)), + // |status| match status { + // VisitResult::Skipped(_) => Flow::Continue, + // VisitResult::Control(flow) => flow, + // }, + // ) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a (), - ) -> Future<'a, Result<ValueKnown<'a, BorrowedStatic<'ctx, I::T>>, ()>, E> { - E::ready(Ok(ValueKnown { preview: None })) + ) -> ObjSafe<'a, Result<ValueKnown<'a, BorrowedStatic<'ctx, I::T>>, ()>, E> { + E::ready(Ok(ValueKnown { preview: None })).into() } } @@ -481,26 +506,29 @@ where E: Effect, I: StructTypeInfo<'ctx, M, S = S>, { + #[inline(always)] fn hint<'a>( &'a mut self, visitor: DynVisitor<'a, 'ctx>, _hint: <SequenceProto<E> as HintMeta>::Hint, - ) -> Future<'a, Flow, E> { - E::map(visit_sequence::<E>(visitor, self), |status| match status { - VisitResult::Skipped(_) => Flow::Continue, - VisitResult::Control(flow) => flow, - }) + ) -> ObjSafe<'a, Flow, E> { + todo!() + // E::map(visit_sequence::<E>(visitor, self), |status| match status { + // VisitResult::Skipped(_) => Flow::Continue, + // VisitResult::Control(flow) => flow, + // }) } + #[inline(always)] fn known<'a>( &'a mut self, _hint: &'a <SequenceProto<E> as HintMeta>::Hint, - ) -> Future<'a, Result<MetaKnown<'a, 'ctx, SequenceProto<E>>, ()>, E> { + ) -> ObjSafe<'a, Result<MetaKnown<'a, 'ctx, SequenceProto<E>>, ()>, E> { let len = I::FIELDS.len(); E::ready(Ok(SequenceKnown { len: (len, Some(len)), - })) + })).into() } } @@ -509,31 +537,34 @@ where E: Effect, I: StructTypeInfo<'ctx, M, S = S>, { - fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E> { + #[inline(always)] + fn size_hint(&mut self) -> ObjSafe<'_, (usize, Option<usize>), E> { let len = I::FIELDS.len(); - E::ready((len, Some(len))) + E::ready((len, Some(len))).into() } - fn next<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Flow, E> { + #[inline(always)] + fn next<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E> { if self.index >= I::FIELDS.len() { - return E::ready(Flow::Done); + return E::ready(Flow::Done).into(); } let index = self.index; self.index += 1; - E::map( - I::walk_field::<E>(index, self.value, visitor), - |result| match result { - Ok(flow) => flow, - Err(err) => { - // Record the error and signal a break. - self.error = Some(StructWalkErrorKind::Field(err)); - Flow::Err - } - }, - ) + todo!() + // E::map( + // I::walk_field::<E>(index, self.value, visitor), + // |result| match result { + // Ok(flow) => flow, + // Err(err) => { + // // Record the error and signal a break. + // self.error = Some(StructWalkErrorKind::Field(err)); + // Flow::Err + // } + // }, + // ) } } @@ -544,123 +575,124 @@ where I::T: 'static, { #[inline(always)] - fn new_walk<'a>(&'a mut self, mut visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Status, E> { + fn new_walk<'a>(&'a mut self, mut visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Status, E> { // Reset the errors to default state. self.error = None; // Reset the field index to the default. self.index = 0; - E::wrap(async move { - // We should check if the visitor wants something specific. - match visit_request_hint::<E>(visitor.cast(), DynWalker(self)).await { - VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue) => {} - VisitResult::Control(Flow::Done) => return Ok(()), - VisitResult::Control(Flow::Err) => return Err(()), - } - - // Attempt to visit the value directly. - match visit_value::<_, E>(visitor.cast(), BorrowedStatic(self.value)).await { - VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue) => {} - VisitResult::Control(Flow::Done) => return Ok(()), - VisitResult::Control(Flow::Err) => return Err(()), - } - - // Follow the standard set of protocols for a struct. - // - Tagged: type ID - // - Tagged: struct - // - Tagged: struct name - // - Tagged: struct field names - // - Sequence: the fields - - match visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( - TagConst, - visitor.cast(), - ValueWalker::new(TypeId::of::<I::T>()), - ) - .await - { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - return Err(()); - } - Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(Flow::Done)) => return Ok(()), - Ok(VisitResult::Control(Flow::Err)) => return Err(()), - } - - match visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( - TagConst, - visitor.cast(), - NoopWalker::new(), - ) - .await - { - Ok(VisitResult::Skipped(_)) => { - match visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>( - TagConst, - visitor.cast(), - NoopWalker::new(), - ) - .await - { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - return Err(()); - } - Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(Flow::Done)) => return Ok(()), - Ok(VisitResult::Control(Flow::Err)) => return Err(()), - } - } - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - return Err(()); - } - Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(Flow::Done)) => return Ok(()), - Ok(VisitResult::Control(Flow::Err)) => return Err(()), - } - - match visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>( - TagConst, - visitor.cast(), - ValueWalker::new(I::NAME), - ) - .await - { - Err(err) => { - self.error = Some(StructWalkErrorKind::Tag(err)); - return Err(()); - } - Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(Flow::Done)) => return Ok(()), - Ok(VisitResult::Control(Flow::Err)) => return Err(()), - } - - match visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>( - TagConst, - visitor.cast(), - StaticSliceWalker::<_, ValueWalker<&'static str>>::new(I::FIELDS), - ) - .await - { - Err(err) => { - self.error = Some(StructWalkErrorKind::FieldTag(err)); - return Err(()); - } - Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} - Ok(VisitResult::Control(Flow::Done)) => return Ok(()), - Ok(VisitResult::Control(Flow::Err)) => return Err(()), - } - - match visit_sequence::<E>(visitor, self).await { - VisitResult::Control(Flow::Continue) | VisitResult::Skipped(_) => {} - VisitResult::Control(Flow::Done) => return Ok(()), - VisitResult::Control(Flow::Err) => return Err(()), - } - - Ok(()) - }) + todo!() + // E::wrap(async move { + // // // We should check if the visitor wants something specific. + // // match visit_request_hint::<E>(visitor.cast(), DynWalker(self)).await { + // // VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue) => {} + // // VisitResult::Control(Flow::Done) => return Ok(()), + // // VisitResult::Control(Flow::Err) => return Err(()), + // // } + // // + // // // Attempt to visit the value directly. + // // match visit_value::<_, E>(visitor.cast(), BorrowedStatic(self.value)).await { + // // VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue) => {} + // // VisitResult::Control(Flow::Done) => return Ok(()), + // // VisitResult::Control(Flow::Err) => return Err(()), + // // } + // // + // // // Follow the standard set of protocols for a struct. + // // // - Tagged: type ID + // // // - Tagged: struct + // // // - Tagged: struct name + // // // - Tagged: struct field names + // // // - Sequence: the fields + // // + // // match visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>( + // // TagConst, + // // visitor.cast(), + // // ValueWalker::new(TypeId::of::<I::T>()), + // // ) + // // .await + // // { + // // Err(err) => { + // // self.error = Some(StructWalkErrorKind::Tag(err)); + // // return Err(()); + // // } + // // Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} + // // Ok(VisitResult::Control(Flow::Done)) => return Ok(()), + // // Ok(VisitResult::Control(Flow::Err)) => return Err(()), + // // } + // // + // // match visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>( + // // TagConst, + // // visitor.cast(), + // // NoopWalker::new(), + // // ) + // // .await + // // { + // // Ok(VisitResult::Skipped(_)) => { + // // match visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>( + // // TagConst, + // // visitor.cast(), + // // NoopWalker::new(), + // // ) + // // .await + // // { + // // Err(err) => { + // // self.error = Some(StructWalkErrorKind::Tag(err)); + // // return Err(()); + // // } + // // Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} + // // Ok(VisitResult::Control(Flow::Done)) => return Ok(()), + // // Ok(VisitResult::Control(Flow::Err)) => return Err(()), + // // } + // // } + // // Err(err) => { + // // self.error = Some(StructWalkErrorKind::Tag(err)); + // // return Err(()); + // // } + // // Ok(VisitResult::Control(Flow::Continue)) => {} + // // Ok(VisitResult::Control(Flow::Done)) => return Ok(()), + // // Ok(VisitResult::Control(Flow::Err)) => return Err(()), + // // } + // // + // // match visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>( + // // TagConst, + // // visitor.cast(), + // // ValueWalker::new(I::NAME), + // // ) + // // .await + // // { + // // Err(err) => { + // // self.error = Some(StructWalkErrorKind::Tag(err)); + // // return Err(()); + // // } + // // Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} + // // Ok(VisitResult::Control(Flow::Done)) => return Ok(()), + // // Ok(VisitResult::Control(Flow::Err)) => return Err(()), + // // } + // // + // // match visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>( + // // TagConst, + // // visitor.cast(), + // // StaticSliceWalker::<_, ValueWalker<&'static str>>::new(I::FIELDS), + // // ) + // // .await + // // { + // // Err(err) => { + // // self.error = Some(StructWalkErrorKind::FieldTag(err)); + // // return Err(()); + // // } + // // Ok(VisitResult::Skipped(_)) | Ok(VisitResult::Control(Flow::Continue)) => {} + // // Ok(VisitResult::Control(Flow::Done)) => return Ok(()), + // // Ok(VisitResult::Control(Flow::Err)) => return Err(()), + // // } + // + // match visit_sequence::<E>(visitor, self).await { + // VisitResult::Control(Flow::Continue) | VisitResult::Skipped(_) => {} + // VisitResult::Control(Flow::Done) => return Ok(()), + // VisitResult::Control(Flow::Err) => return Err(()), + // } + // + // Ok(()) + // }) } } diff --git a/src/walk/walkers/core/tag.rs b/src/walk/walkers/core/tag.rs index 29a450e..ff8faa3 100644 --- a/src/walk/walkers/core/tag.rs +++ b/src/walk/walkers/core/tag.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use crate::{ any::OwnedStatic, any_trait, - effect::{Effect, Future}, + effect::{Effect, ObjSafe}, never::Never, protocol::{ visitor::{ @@ -43,32 +43,34 @@ where T: Sync, &'static T: Into<W>, { + #[inline(always)] fn walk<'a>( mut self, mut visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { - E::wrap(async move { - match visit_request_hint::<E>(visitor.cast(), DynWalker(&mut self)).await { - VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue) => {} - _ => return Ok(()), - } - - match visit_value::<_, E>(visitor.cast(), OwnedStatic(self.names)).await { - VisitResult::Skipped(_) => {} - VisitResult::Control(Flow::Continue) => {} - _ => return Ok(()), - } - - if let Some(object) = visitor.cast().upcast_mut::<SequenceProto<E>>() { - // Visit with the name. Ignore the flow because we return a result not a flow. - let _ = object.visit(&mut self).await; - } - - Ok(()) - }) + todo!() + // E::wrap(async move { + // match visit_request_hint::<E>(visitor.cast(), DynWalker(&mut self)).await { + // VisitResult::Skipped(_) | VisitResult::Control(Flow::Continue) => {} + // _ => return Ok(()), + // } + // + // match visit_value::<_, E>(visitor.cast(), OwnedStatic(self.names)).await { + // VisitResult::Skipped(_) => {} + // VisitResult::Control(Flow::Continue) => {} + // _ => return Ok(()), + // } + // + // if let Some(object) = visitor.cast().upcast_mut::<SequenceProto<E>>() { + // // Visit with the name. Ignore the flow because we return a result not a flow. + // let _ = object.visit(&mut self).await; + // } + // + // Ok(()) + // }) } } @@ -84,21 +86,24 @@ where T: Sync, &'static T: Into<W>, { - fn next<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> Future<'a, Flow, E> { + #[inline(always)] + fn next<'a>(&'a mut self, visitor: DynVisitor<'a, 'ctx>) -> ObjSafe<'a, Flow, E> { if let Some(name) = self.names.get(self.current) { self.current += 1; - E::wrap(async move { - match crate::Walker::walk(name.into(), visitor).await { - Ok(()) => Flow::Continue, - Err(_) => unreachable!(), - } - }) + todo!() + // E::wrap(async move { + // match crate::Walker::walk(name.into(), visitor).await { + // Ok(()) => Flow::Continue, + // Err(_) => unreachable!(), + // } + // }) } else { - E::ready(Flow::Done) + E::ready(Flow::Done).into() } } - fn size_hint(&mut self) -> Future<'_, (usize, Option<usize>), E> { - E::ready((self.names.len(), Some(self.names.len()))) + #[inline(always)] + fn size_hint(&mut self) -> ObjSafe<'_, (usize, Option<usize>), E> { + E::ready((self.names.len(), Some(self.names.len()))).into() } } diff --git a/src/walk/walkers/core/value.rs b/src/walk/walkers/core/value.rs index c33b2fe..62f5450 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, Future}, + effect::{Effect, ObjSafe}, never::Never, protocol::{visitor::visit_value, DynVisitor}, WalkerTypes, @@ -15,18 +15,21 @@ pub struct ValueWalker<T>(T); impl<T> ValueWalker<T> { /// Create walker from a value. + #[inline(always)] pub fn new(value: T) -> Self { Self(value) } } impl<T> From<T> for ValueWalker<T> { + #[inline(always)] fn from(value: T) -> Self { Self::new(value) } } impl<T: Copy> From<&T> for ValueWalker<T> { + #[inline(always)] fn from(value: &T) -> Self { Self::new(*value) } @@ -39,18 +42,20 @@ 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>( self, visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { // Attempt to visit using the value protocol. - E::map( - visit_value::<_, E>(visitor, OwnedStatic(self.0)), - |_| Ok(()), - ) + todo!() + // E::map( + // visit_value::<_, E>(visitor, OwnedStatic(self.0)), + // |_| Ok(()), + // ) } } @@ -61,6 +66,7 @@ pub struct BorrowWalker<'ctx, T: ?Sized>(&'ctx T); impl<'ctx, T: ?Sized> BorrowWalker<'ctx, T> { /// Create walker from a value. + #[inline(always)] pub fn new(value: &'ctx T) -> Self { Self(value) } @@ -75,16 +81,18 @@ impl<'ctx, T: ?Sized> WalkerTypes for BorrowWalker<'ctx, T> { impl<'ctx, T: ?Sized + Send + Sync + 'static, E: Effect> crate::Walker<'ctx, E> for BorrowWalker<'ctx, T> { + #[inline(always)] fn walk<'a>( self, visitor: DynVisitor<'a, 'ctx>, - ) -> Future<'a, Result<Self::Output, Self::Error>, E> + ) -> ObjSafe<'a, Result<Self::Output, Self::Error>, E> where Self: 'a, { // Attempt to visit using the value protocol. - E::map(visit_value::<_, E>(visitor, BorrowedStatic(self.0)), |_| { - Ok(()) - }) + todo!() + // E::map(visit_value::<_, E>(visitor, BorrowedStatic(self.0)), |_| { + // Ok(()) + // }) } } diff --git a/tests/builder_struct.rs b/tests/builder_struct.rs index 8f85854..27e55f5 100644 --- a/tests/builder_struct.rs +++ b/tests/builder_struct.rs @@ -17,9 +17,9 @@ use treaty::{ Build, Builder, DefaultMode, Flow, Walk, Walker, }; -use crate::common::{protocol::sequence::MockSequenceScope, walker::MockWalker}; - -mod common; +// use crate::common::{protocol::sequence::MockSequenceScope, walker::MockWalker}; +// +// mod common; #[derive(Debug, PartialEq)] struct X { @@ -40,6 +40,7 @@ impl<'ctx, M> walkers::core::r#struct::StructTypeInfo<'ctx, M> for Info { type T = X; + #[inline(always)] fn walk_field<'a, E: Effect>( index: usize, value: &'ctx Self::T, @@ -85,6 +86,7 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo type T = X; + #[inline(always)] fn marker_from_index(index: usize) -> Option<Self::FieldMarker> { match index { 0 => Some(FieldMarker::A), @@ -93,6 +95,7 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo } } + #[inline(always)] fn marker_from_name(name: &str) -> Option<Self::FieldMarker> { match name { "a" => Some(FieldMarker::A), @@ -103,6 +106,7 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo type Error = (); + #[inline(always)] fn from_builders<'a>(builders: Self::Builders) -> Future<'a, Result<Self::T, Self::Error>, E> { E::wrap(async { Ok(X { @@ -112,6 +116,7 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo }) } + #[inline(always)] fn as_visitor<'a>( marker: Self::FieldMarker, builders: &'a mut Self::Builders, @@ -124,6 +129,7 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo type Seed = (); + #[inline(always)] fn new_builders<'a>(_seed: Self::Seed) -> Future<'a, Self::Builders, E> { E::wrap(async { Fields { @@ -134,152 +140,152 @@ impl<'ctx, M, E: Effect> builders::core::r#struct::StructTypeInfo<'ctx, M, E> fo } } -#[test] -#[ignore] -fn demo() { - let value = X { a: true, b: false }; - - let (other, _) = transform::<StructBuilder<Info, DefaultMode, _>, _, Blocking>( - (), - StructWalker::<Info, _, DefaultMode, _>::new(&value), - ) - .value(); - - assert_eq!(other.unwrap(), value); -} - -#[test] -fn from_basic_tuple_like() { - // A tuple like is just a sequence. - let mut scope = MockSequenceScope::<Blocking>::new(); - - // First field. - scope.expect_next().once().returning(|visitor| { - // Visit a bool value. - // - // The bool visitor should report that it is done. - assert_eq!( - visit_value::<_, Blocking>(visitor, OwnedStatic(true)).value(), - VisitResult::Control(Flow::Done) - ); - - // We have another field. - Flow::Continue - }); - - // Second field. - scope.expect_next().once().returning(|visitor| { - // Visit a bool value. - // - // The bool visitor should report that it is done. - assert_eq!( - visit_value::<_, Blocking>(visitor, OwnedStatic(false)).value(), - VisitResult::Control(Flow::Done) - ); - - // No more fields. - Flow::Done - }); - - let mut builder = StructBuilder::<Info, DefaultMode, Blocking>::from_seed(()).value(); - let visitor = builder.as_visitor(); - - // Visit the sequence of field values. - assert!(matches!( - visit_sequence(visitor, &mut scope).value(), - VisitResult::Control(Flow::Done) - )); - - assert_eq!(builder.build().value().unwrap(), X { a: true, b: false }); -} - -#[test] -fn from_basic_map_like() { - // A map is built from a sequence. - let mut scope = MockSequenceScope::<Blocking>::new(); - - // Here we do the b field first to show a map-like doesn't care about order. - scope.expect_next().once().returning(|mut visitor| { - let mut walker = MockWalker::<(), ()>::new(); - - // We need to give the b field name in the key tag. - walker.expect_walk().once().returning(|visitor| { - assert_eq!( - visit_value::<_, Blocking>(visitor, TempBorrowedStatic("b")).value(), - VisitResult::Control(Flow::Done) - ); - - Ok(()) - }); - - // Tag the value with a key as the field name. - assert_eq!( - visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).value(), - Ok(VisitResult::Control(Flow::Continue)), - ); - - // Visit the value as normal. - assert_eq!( - visit_value::<_, Blocking>(visitor, OwnedStatic(true)).value(), - VisitResult::Control(Flow::Done) - ); - - // There is another field. - Flow::Continue - }); - - // The other field. - scope.expect_next().once().returning(|mut visitor| { - let mut walker = MockWalker::<(), ()>::new(); - - // Here we do field a. - walker.expect_walk().once().returning(|visitor| { - assert_eq!( - visit_value::<_, Blocking>(visitor, TempBorrowedStatic("a")).value(), - VisitResult::Control(Flow::Done) - ); - - Ok(()) - }); - - // Tag the value with a key. - assert_eq!( - visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).value(), - Ok(VisitResult::Control(Flow::Continue)), - ); - - // The field value. - assert_eq!( - visit_value::<_, Blocking>(visitor, OwnedStatic(false)).value(), - VisitResult::Control(Flow::Done) - ); - - // The sequence protocol allows for us to wait to decide if there is another item. - Flow::Continue - }); - - // There are no more fields. - scope.expect_next().once().returning(|_visitor| Flow::Done); - - let mut builder = StructBuilder::<Info, DefaultMode, Blocking>::from_seed(()).value(); - let mut visitor = builder.as_visitor(); - - // We need to provide the map tag to the struct before getting into the sequence. - // This tag notifies the struct builder to expect the sequence as a map. - assert_eq!( - visit_tag::<tags::Map, Blocking, _>(TagConst, visitor.cast(), NoopWalker::new()).value(), - Ok(VisitResult::Control(Flow::Continue)) - ); - - // Visit the sequence of fields. - assert_eq!( - visit_sequence(visitor, &mut scope).value(), - VisitResult::Control(Flow::Done) - ); - - // The struct is built as the mock walker above makes it. - assert_eq!(builder.build().value().unwrap(), X { a: false, b: true }); -} +// #[test] +// #[ignore] +// fn demo() { +// let value = X { a: true, b: false }; +// +// let (other, _) = transform::<StructBuilder<Info, DefaultMode, _>, _, Blocking>( +// (), +// StructWalker::<Info, _, DefaultMode, _>::new(&value), +// ) +// .value(); +// +// assert_eq!(other.unwrap(), value); +// } +// +// #[test] +// fn from_basic_tuple_like() { +// // A tuple like is just a sequence. +// let mut scope = MockSequenceScope::<Blocking>::new(); +// +// // First field. +// scope.expect_next().once().returning(|visitor| { +// // Visit a bool value. +// // +// // The bool visitor should report that it is done. +// assert_eq!( +// visit_value::<_, Blocking>(visitor, OwnedStatic(true)).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// // We have another field. +// Flow::Continue +// }); +// +// // Second field. +// scope.expect_next().once().returning(|visitor| { +// // Visit a bool value. +// // +// // The bool visitor should report that it is done. +// assert_eq!( +// visit_value::<_, Blocking>(visitor, OwnedStatic(false)).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// // No more fields. +// Flow::Done +// }); +// +// let mut builder = StructBuilder::<Info, DefaultMode, Blocking>::from_seed(()).value(); +// let visitor = builder.as_visitor(); +// +// // Visit the sequence of field values. +// assert!(matches!( +// visit_sequence(visitor, &mut scope).value(), +// VisitResult::Control(Flow::Done) +// )); +// +// assert_eq!(builder.build().value().unwrap(), X { a: true, b: false }); +// } +// +// #[test] +// fn from_basic_map_like() { +// // A map is built from a sequence. +// let mut scope = MockSequenceScope::<Blocking>::new(); +// +// // Here we do the b field first to show a map-like doesn't care about order. +// scope.expect_next().once().returning(|mut visitor| { +// let mut walker = MockWalker::<(), ()>::new(); +// +// // We need to give the b field name in the key tag. +// walker.expect_walk().once().returning(|visitor| { +// assert_eq!( +// visit_value::<_, Blocking>(visitor, TempBorrowedStatic("b")).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// Ok(()) +// }); +// +// // Tag the value with a key as the field name. +// assert_eq!( +// visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).value(), +// Ok(VisitResult::Control(Flow::Continue)), +// ); +// +// // Visit the value as normal. +// assert_eq!( +// visit_value::<_, Blocking>(visitor, OwnedStatic(true)).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// // There is another field. +// Flow::Continue +// }); +// +// // The other field. +// scope.expect_next().once().returning(|mut visitor| { +// let mut walker = MockWalker::<(), ()>::new(); +// +// // Here we do field a. +// walker.expect_walk().once().returning(|visitor| { +// assert_eq!( +// visit_value::<_, Blocking>(visitor, TempBorrowedStatic("a")).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// Ok(()) +// }); +// +// // Tag the value with a key. +// assert_eq!( +// visit_tag::<tags::Key, Blocking, _>(TagConst, visitor.cast(), walker).value(), +// Ok(VisitResult::Control(Flow::Continue)), +// ); +// +// // The field value. +// assert_eq!( +// visit_value::<_, Blocking>(visitor, OwnedStatic(false)).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// // The sequence protocol allows for us to wait to decide if there is another item. +// Flow::Continue +// }); +// +// // There are no more fields. +// scope.expect_next().once().returning(|_visitor| Flow::Done); +// +// let mut builder = StructBuilder::<Info, DefaultMode, Blocking>::from_seed(()).value(); +// let mut visitor = builder.as_visitor(); +// +// // We need to provide the map tag to the struct before getting into the sequence. +// // This tag notifies the struct builder to expect the sequence as a map. +// assert_eq!( +// visit_tag::<tags::Map, Blocking, _>(TagConst, visitor.cast(), NoopWalker::new()).value(), +// Ok(VisitResult::Control(Flow::Continue)) +// ); +// +// // Visit the sequence of fields. +// assert_eq!( +// visit_sequence(visitor, &mut scope).value(), +// VisitResult::Control(Flow::Done) +// ); +// +// // The struct is built as the mock walker above makes it. +// assert_eq!(builder.build().value().unwrap(), X { a: false, b: true }); +// } pub mod demo { use crate::Walk; |