nesting structs works in the Walk derive macro
Konnor Andrews 2024-04-08
parent b8a516e · commit 05b755f
-rw-r--r--src/build.rs18
-rw-r--r--src/build/builders/core/bool.rs27
-rw-r--r--src/build/builders/debug.rs120
-rw-r--r--src/effect.rs48
-rw-r--r--src/lib.rs170
-rw-r--r--src/macros.rs64
-rw-r--r--src/protocol/visitor.rs11
-rw-r--r--src/protocol/visitor/request_hint.rs49
-rw-r--r--src/protocol/visitor/sequence.rs62
-rw-r--r--src/protocol/visitor/tag.rs12
-rw-r--r--src/protocol/visitor/value.rs96
-rw-r--r--src/transform.rs8
-rw-r--r--src/walk.rs66
-rw-r--r--src/walk/walkers/core.rs2
-rw-r--r--src/walk/walkers/core/array.rs6
-rw-r--r--src/walk/walkers/core/bool.rs60
-rw-r--r--src/walk/walkers/core/noop.rs36
-rw-r--r--src/walk/walkers/core/tag.rs268
-rw-r--r--src/walk/walkers/core/value.rs89
19 files changed, 651 insertions, 561 deletions
diff --git a/src/build.rs b/src/build.rs
index 5a6b526..24232a0 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -6,15 +6,9 @@ use crate::{
};
/// A buildable type.
-pub trait Build<'ctx>: BuilderTypes<Value = Self> + Send {
+pub trait Build<'ctx, M, E: Effect<'ctx>>: BuilderTypes<Value = Self> + Send {
/// The builder that can be used to build a value of `Self`.
- type Builder<E: Effect<'ctx>>: Builder<
- 'ctx,
- Seed = Self::Seed,
- Error = Self::Error,
- Value = Self,
- Effect = E,
- >;
+ type Builder: Builder<'ctx, E, Seed = Self::Seed, Error = Self::Error, Value = Self>;
}
pub trait BuilderTypes {
@@ -40,10 +34,8 @@ pub trait BuilderTypes {
/// the builder with data from it's walk.
/// - Call [`Self::build()`] to finish building the value and get any errors
/// that happened during filling it with data.
-pub trait Builder<'ctx>: BuilderTypes + Sized + Send {
- type Effect: Effect<'ctx>;
-
- fn from_seed<'a>(seed: Self::Seed) -> Future<'a, 'ctx, Self, Self::Effect>
+pub trait Builder<'ctx, E: Effect<'ctx>>: BuilderTypes + Sized + Send {
+ fn from_seed<'a>(seed: Self::Seed) -> Future<'a, 'ctx, Self, E>
where
Self: 'a;
@@ -51,7 +43,7 @@ pub trait Builder<'ctx>: BuilderTypes + Sized + Send {
///
/// If an error happened with the builder during the walk
/// it will be reported here.
- fn build<'a>(self) -> Future<'a, 'ctx, Result<Self::Value, Self::Error>, Self::Effect>
+ fn build<'a>(self) -> Future<'a, 'ctx, Result<Self::Value, Self::Error>, E>
where
Self: 'a;
diff --git a/src/build/builders/core/bool.rs b/src/build/builders/core/bool.rs
index 241f1e4..7a95820 100644
--- a/src/build/builders/core/bool.rs
+++ b/src/build/builders/core/bool.rs
@@ -4,11 +4,15 @@ use crate::{
any::static_wrapper::OwnedStatic,
any_trait,
effect::{Effect, Future},
- protocol::{visitor::value::Value, Visitor},
+ protocol::{
+ visitor::value::{DynValue, Value},
+ Visitor,
+ },
+ Flow,
};
-impl<'ctx> crate::Build<'ctx> for bool {
- type Builder<E: Effect<'ctx>> = Builder<E>;
+impl<'ctx, M, E: Effect<'ctx>> crate::Build<'ctx, M, E> for bool {
+ type Builder = Builder<E>;
}
#[derive(Debug)]
@@ -34,9 +38,7 @@ impl<E> crate::BuilderTypes for Builder<E> {
type Seed = ();
}
-impl<'ctx, E: Effect<'ctx>> crate::Builder<'ctx> for Builder<E> {
- type Effect = E;
-
+impl<'ctx, E: Effect<'ctx>> crate::Builder<'ctx, E> for Builder<E> {
#[inline]
fn build<'a>(self) -> Future<'a, 'ctx, Result<Self::Value, Self::Error>, E>
where
@@ -59,19 +61,14 @@ impl<'ctx, E: Effect<'ctx>> crate::Builder<'ctx> for Builder<E> {
any_trait! {
impl['a, 'ctx, E] Builder<E> = [
- dyn Value<'a, 'ctx, OwnedStatic<bool>, Effect = E> + 'a,
+ DynValue<'a, 'ctx, OwnedStatic<bool>, E>,
] where E: Effect<'ctx>
}
-impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<bool>> for Builder<E> {
- type Effect = E;
-
+impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<bool>, E> for Builder<E> {
#[inline]
- fn visit(
- &'a mut self,
- OwnedStatic(value): OwnedStatic<bool>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> {
+ fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Future<'a, 'ctx, Flow, E> {
self.0 = Some(value);
- E::wrap(core::future::ready(ControlFlow::Continue(())))
+ E::ready(Flow::Continue)
}
}
diff --git a/src/build/builders/debug.rs b/src/build/builders/debug.rs
index 3bc9e94..c8f9324 100644
--- a/src/build/builders/debug.rs
+++ b/src/build/builders/debug.rs
@@ -8,9 +8,10 @@ use crate::{
protocol::{
self,
visitor::{
- request_hint::RequestHint,
- tag::{Dyn, Tag, DynTag},
- value::Value, sequence::{DynSequence, Sequence, SequenceFlow},
+ request_hint::{DynRequestHint, RequestHint},
+ sequence::{DynSequence, Sequence},
+ tag::{Dyn, DynTag, Tag},
+ value::{DynValue, Value},
},
},
DynWalker, Flow,
@@ -20,17 +21,19 @@ pub struct Visitor<E>(usize, PhantomData<fn() -> E>);
any_trait! {
impl['a, 'ctx, E] Visitor<E> = [
- dyn RequestHint<'ctx, Effect = E> + 'a,
+ DynRequestHint<'a, 'ctx, E>,
DynTag<'a, 'ctx, Dyn, E>,
- dyn Value<'a, 'ctx, OwnedStatic<&'static str>, Effect = E> + 'a,
- dyn Value<'a, 'ctx, OwnedStatic<TypeId>, Effect = E> + 'a,
- dyn Value<'a, 'ctx, OwnedStatic<usize>, Effect = E> + 'a,
+ DynValue<'a, 'ctx, OwnedStatic<&'static str>, E>,
+ DynValue<'a, 'ctx, OwnedStatic<TypeId>, E>,
+ DynValue<'a, 'ctx, OwnedStatic<usize>, E>,
+ DynValue<'a, 'ctx, OwnedStatic<bool>, E>,
+ // DynValue<'a, 'ctx, OwnedStatic<&'static [&'static str]>, E>,
DynSequence<'a, 'ctx, E>,
] else fallback where E: Effect<'ctx>
}
fn fallback(id: LtTypeId<'_>) {
- println!("Unknown trait: {}", id);
+ // println!("Unknown trait: {}", id);
}
impl<'ctx, E: Effect<'ctx>> Visitor<E> {
@@ -45,33 +48,23 @@ impl<'ctx, E: Effect<'ctx>> Visitor<E> {
}
}
-impl<'ctx, E: Effect<'ctx>> RequestHint<'ctx> for Visitor<E> {
- type Effect = E;
-
+impl<'ctx, E: Effect<'ctx>> RequestHint<'ctx, E> for Visitor<E> {
fn request_hint<'a>(
&'a mut self,
_walker: crate::protocol::Walker<'a, 'ctx>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
- where
- Self: 'a,
- {
+ ) -> Future<'a, 'ctx, Flow, E> {
self.tab();
println!("Visit request hint (no hint given)");
- E::wrap(async { ControlFlow::Continue(()) })
+ E::ready(Flow::Continue)
}
}
-impl<'ctx, E: Effect<'ctx>> Tag<'ctx, Dyn> for Visitor<E> {
- type Effect = E;
-
+impl<'ctx, E: Effect<'ctx>> Tag<'ctx, Dyn, E> for Visitor<E> {
fn visit<'a>(
&'a mut self,
kind: Dyn,
- walker: DynWalker<'a, 'ctx, Self::Effect>,
- ) -> Future<'a, 'ctx, Flow<Never>, Self::Effect>
- where
- Self: 'a,
- {
+ walker: DynWalker<'a, 'ctx, E>,
+ ) -> Future<'a, 'ctx, Flow, E> {
self.tab();
println!("Visit tag: {}", kind.0);
@@ -79,86 +72,99 @@ impl<'ctx, E: Effect<'ctx>> Tag<'ctx, Dyn> for Visitor<E> {
self.0 += 1;
let result = walker.walk(self).await;
self.0 -= 1;
- match result {
- ControlFlow::Continue(()) => Flow::Continue,
- ControlFlow::Break(()) => Flow::Break,
- }
+ result
})
}
}
-impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<&'static str>> for Visitor<E> {
- type Effect = E;
-
+impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<&'static str>, E> for Visitor<E> {
fn visit(
&'a mut self,
OwnedStatic(value): OwnedStatic<&'static str>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+ ) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a,
{
self.tab();
println!("Visit static str: {:?}", value);
- E::wrap(async { ControlFlow::Continue(()) })
+ E::ready(Flow::Continue)
}
}
-impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<usize>> for Visitor<E> {
- type Effect = E;
-
- fn visit(
- &'a mut self,
- OwnedStatic(value): OwnedStatic<usize>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<usize>, E> for Visitor<E> {
+ fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<usize>) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a,
{
self.tab();
println!("Visit usize: {}", value);
- E::wrap(async { ControlFlow::Continue(()) })
+ E::ready(Flow::Continue)
}
}
-impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<TypeId>> for Visitor<E> {
- type Effect = E;
+impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<bool>, E> for Visitor<E> {
+ fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> Future<'a, 'ctx, Flow, E>
+ where
+ Self: 'a,
+ {
+ self.tab();
+ println!("Visit bool: {}", value);
+ E::ready(Flow::Continue)
+ }
+}
+impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<&'static [&'static str]>, E>
+ for Visitor<E>
+{
fn visit(
&'a mut self,
- OwnedStatic(value): OwnedStatic<TypeId>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+ OwnedStatic(value): OwnedStatic<&'static [&'static str]>,
+ ) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a,
{
self.tab();
- println!("Visit type ID: {:?}", value);
- E::wrap(async { ControlFlow::Continue(()) })
+ println!("Visit static slice of static str: {:?}", value);
+ E::ready(Flow::Continue)
}
}
-impl<'ctx, E: Effect<'ctx>> Sequence<'ctx> for Visitor<E> {
- type Effect = E;
+impl<'a, 'ctx: 'a, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<TypeId>, E> for Visitor<E> {
+ fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<TypeId>) -> Future<'a, 'ctx, Flow, E>
+ where
+ Self: 'a,
+ {
+ self.tab();
+ println!("Visit type ID: {:?}", value);
+ E::ready(Flow::Continue)
+ }
+}
+impl<'ctx, E: Effect<'ctx>> Sequence<'ctx, E> for Visitor<E> {
fn visit<'a>(
&'a mut self,
- scope: protocol::visitor::sequence::DynSequenceScope<'a, 'ctx, Self::Effect>,
- ) -> Future<'a, 'ctx, Flow<Never>, Self::Effect> {
+ scope: protocol::visitor::sequence::DynSequenceScope<'a, 'ctx, E>,
+ ) -> Future<'a, 'ctx, Flow, E> {
self.tab();
E::wrap(async {
println!("Visit sequence, size hint: {:?}", scope.size_hint().await);
self.0 += 1;
+
+ let mut index = 0;
let flow = loop {
self.tab();
- println!("Calling next");
+ println!("Calling next: {}", index);
self.0 += 1;
match scope.next(self).await {
- SequenceFlow::Done => {
+ Flow::Done => {
self.tab();
println!("Sequence done");
- break Flow::Continue
- },
- SequenceFlow::Continue => {},
- SequenceFlow::Break => break Flow::Break,
+ break Flow::Continue;
+ }
+ Flow::Continue => {}
+ Flow::Break => break Flow::Break,
}
+ index += 1;
self.0 -= 1;
};
self.0 -= 2;
diff --git a/src/effect.rs b/src/effect.rs
index ebf082e..3ce7a07 100644
--- a/src/effect.rs
+++ b/src/effect.rs
@@ -28,6 +28,15 @@ pub trait Effect<'ctx>: 'static {
fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T>;
+ fn map<'a, T, U, F>(
+ future: SendFuture::T<'a, 'ctx, Self::Future<T>, T>,
+ func: F,
+ ) -> SendFuture::T<'a, 'ctx, Self::Future<U>, U>
+ where
+ T: Send,
+ U: Send,
+ F: FnOnce(T) -> U + Send + 'a;
+
#[cfg(feature = "alloc")]
#[inline]
fn wrap_boxed<'a, F>(
@@ -114,6 +123,19 @@ impl<'ctx, B: BlockOn> Effect<'ctx> for Blocking<B> {
fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T> {
core::future::ready(value)
}
+
+ fn map<'a, T, U, F>(
+ future: SendFuture::T<'a, 'ctx, Self::Future<T>, T>,
+ func: F,
+ ) -> SendFuture::T<'a, 'ctx, Self::Future<U>, U>
+ where
+ T: Send,
+ U: Send,
+ F: FnOnce(T) -> U + Send + 'a,
+ {
+ let value = B::block_on(future);
+ core::future::ready(func(value))
+ }
}
mod sealed {
@@ -160,6 +182,28 @@ impl<'ctx> Effect<'ctx> for Async {
sealed::BoxedFuture::Box(Box::pin(future))
}
+ fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T> {
+ sealed::BoxedFuture::Ready(core::future::ready(value))
+ }
+
+ fn map<'a, T, U, F>(
+ future: SendFuture::T<'a, 'ctx, Self::Future<T>, T>,
+ func: F,
+ ) -> SendFuture::T<'a, 'ctx, Self::Future<U>, U>
+ where
+ T: Send,
+ U: Send,
+ F: FnOnce(T) -> U + Send + 'a,
+ {
+ match future {
+ sealed::BoxedFuture::Box(future) => Self::wrap(async { func(future.await) }),
+ sealed::BoxedFuture::Ready(future) => {
+ let value = Spin::block_on(future);
+ Self::ready(func(value))
+ }
+ }
+ }
+
fn wrap_boxed<'a, F>(
future: core::pin::Pin<Box<F>>,
) -> SendFuture::T<'a, 'ctx, Self::Future<F::Output>, F::Output>
@@ -169,8 +213,4 @@ impl<'ctx> Effect<'ctx> for Async {
{
sealed::BoxedFuture::Box(future)
}
-
- fn ready<'a, T: Send>(value: T) -> SendFuture::T<'a, 'ctx, Self::Future<T>, T> {
- sealed::BoxedFuture::Ready(core::future::ready(value))
- }
}
diff --git a/src/lib.rs b/src/lib.rs
index 03b2e0d..c1709cc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -40,42 +40,48 @@ pub mod macros;
pub mod never {
mod sealed {
pub trait Extract {
- type T;
+ type Never;
}
impl<T> Extract for fn() -> T {
- type T = T;
+ type Never = T;
}
}
- #[doc(hidden)]
- pub type Never = <fn() -> ! as sealed::Extract>::T;
+ /// Test
+ pub type Never = <fn() -> ! as sealed::Extract>::Never;
}
pub const TAG_TYPE_NAME: Symbol = Symbol::new("Type Name");
pub const TAG_TYPE_ID: Symbol = Symbol::new("Type ID");
pub const TAG_TYPE_SIZE: Symbol = Symbol::new("Type Size");
pub const TAG_FIELD_NAMES: Symbol = Symbol::new("Field Names");
+pub const TAG_KEY: Symbol = Symbol::new("Key");
pub const TAG_SEQ_INDEX: Symbol = Symbol::new("Seq Index");
pub const TAG_SEQ_LEN: Symbol = Symbol::new("Seq Length");
pub const TAG_STRUCT: Symbol = Symbol::new("Struct");
+pub const TAG_FIELD: Symbol = Symbol::new("Field");
pub const TAG_ENUM: Symbol = Symbol::new("Enum");
+pub enum DefaultMode {}
+
#[derive(Debug)]
pub enum StructWalkError {
- Tag(TagError),
+ Tag(TagError<never::Never>),
}
#[must_use]
-pub enum Flow<Error> {
+pub enum Flow {
/// Processing should continue as normal.
Continue,
- /// Processing should stop, but there is no direct error to report.
+ /// Processing should stop.
+ ///
+ /// This state signals some error happened.
Break,
- /// Processing should stop with this error.
- Err(Error),
+ /// Processing should stop.
+ Done,
}
#[macro_export]
@@ -87,12 +93,13 @@ macro_rules! Walk {
),* $(,)?}
} => {
const _: () = {
- impl<'ctx> $crate::Walk<'ctx> for &'ctx $name {
- type Walker<E: $crate::effect::Effect<'ctx>> = Walker<'ctx, E>;
+ impl<'ctx, M, E: $crate::effect::Effect<'ctx>> $crate::Walk<'ctx, M, E> for &'ctx $name {
+ type Walker = Walker<'ctx, M>;
- fn into_walker<E: $crate::effect::Effect<'ctx>>(self) -> Self::Walker<E> {
+ fn into_walker(self) -> Self::Walker {
Walker {
value: self,
+ field: 0,
_marker: ::core::marker::PhantomData,
}
}
@@ -103,36 +110,35 @@ macro_rules! Walk {
type Output = ();
}
- pub struct Walker<'ctx, E> {
+ pub struct Walker<'ctx, M> {
value: &'ctx $name,
- _marker: ::core::marker::PhantomData<fn() -> E>,
+ field: usize,
+ _marker: ::core::marker::PhantomData<fn() -> M>,
}
- impl<'ctx, E> $crate::WalkerTypes for Walker<'ctx, E> {
+ impl<'ctx, M> $crate::WalkerTypes for Walker<'ctx, M> {
type Error = $crate::StructWalkError;
type Output = ();
}
- impl<'ctx, E: $crate::effect::Effect<'ctx>> $crate::Walker<'ctx> for Walker<'ctx, E> {
- type Effect = E;
-
+ impl<'ctx, E: $crate::effect::Effect<'ctx>, M> $crate::Walker<'ctx, E> for Walker<'ctx, M> {
fn walk<'a>(
mut self,
visitor: $crate::protocol::Visitor<'a, 'ctx>,
- ) -> $crate::effect::Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
+ ) -> $crate::effect::Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
where
Self: 'a
{
E::wrap(async move {
// We should check if the visitor wants something specific.
- if let Some(object) = visitor.upcast_mut::<dyn $crate::protocol::visitor::request_hint::RequestHint<'ctx, Effect = E> + '_>() {
+ if let Some(object) = visitor.upcast_mut::<$crate::protocol::visitor::request_hint::DynRequestHint<'_, 'ctx, E>>() {
// Allow the visitor to give a hint if it wants.
match object.request_hint(&mut self).await {
- ::core::ops::ControlFlow::Continue(()) => {
+ $crate::Flow::Continue => {
// The visitor wants the walker to continue to it's normal
// walking.
},
- ::core::ops::ControlFlow::Break(()) => {
+ _ => {
// The visitor is done (either because of an error or because
// it already used a hint).
return Ok(());
@@ -146,53 +152,114 @@ macro_rules! Walk {
// - Tagged: struct field names
// - Sequence: the fields
- match $crate::macros::visit_tag::<{ $crate::TAG_STRUCT.to_int() }, E, _>(
+ // Attempt to visit the value directly.
+ if !matches!($crate::protocol::visitor::value::visit_value::<_, E>(
visitor,
- $crate::walkers::core::tag::NoopWalker::new()
+ $crate::any::static_wrapper::BorrowedStatic(self.value)
+ ).await, $crate::protocol::visitor::Status::Skipped) {
+ return Ok(());
+ }
+
+ // Describe the struct in a general way:
+
+ // Give the type ID
+ match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_ID.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::value::ValueWalker::new(::core::any::TypeId::of::<$name>())
).await {
- $crate::Flow::Continue => {},
- $crate::Flow::Break => return Ok(()),
- $crate::Flow::Err(_) => unreachable!(),
+ Ok($crate::Flow::Continue) => {},
+ Ok(_) => return Ok(()),
+ Err(_) => unreachable!(),
}
- match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_NAME.to_int() }, E, _>(
+ // Signal this is a struct.
+ match $crate::macros::visit_tag::<{ $crate::TAG_STRUCT.to_int() }, E, _>(
visitor,
- $crate::walkers::core::tag::ValueWalker::new(stringify!($name))
+ $crate::walkers::core::noop::NoopWalker::new()
).await {
- $crate::Flow::Continue => {},
- $crate::Flow::Break => return Ok(()),
- $crate::Flow::Err(err) => return Err(StructWalkError::Tag(err)),
+ Ok($crate::Flow::Continue) => {},
+ _ => return Ok(()),
}
- match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_ID.to_int() }, E, _>(
+ // Give the type name.
+ match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_NAME.to_int() }, E, _>(
visitor,
- $crate::walkers::core::tag::ValueWalker::new(::core::any::TypeId::of::<$name>())
+ $crate::walkers::core::value::ValueWalker::new(stringify!($name))
).await {
- $crate::Flow::Continue => {},
- $crate::Flow::Break => return Ok(()),
- $crate::Flow::Err(err) => return Err(StructWalkError::Tag(err)),
+ Ok($crate::Flow::Continue) => {},
+ Ok(_) => return Ok(()),
+ Err(_) => unreachable!(),
}
+ // Give the field names before hand.
match $crate::macros::visit_tag::<{ $crate::TAG_FIELD_NAMES.to_int() }, E, _>(
visitor,
- $crate::walkers::core::tag::NamesWalker::new(&[$(
+ $crate::walkers::core::tag::StaticSliceWalker::<_, $crate::walkers::core::value::ValueWalker<&str>>::new(&[$(
stringify!($field)
),*])
).await {
- $crate::Flow::Continue => {},
- $crate::Flow::Break => return Ok(()),
- $crate::Flow::Err(err) => return Err(StructWalkError::Tag(err)),
+ Ok($crate::Flow::Continue) => {},
+ Ok(_) => return Ok(()),
+ // Err(err) => return Err(StructWalkError::Tag(err)),
+ Err(err) => todo!(),
+ }
+
+ if !matches!($crate::protocol::visitor::sequence::visit_sequence::<E>(
+ visitor,
+ &mut self,
+ ).await, $crate::protocol::visitor::Status::Skipped) {
+ return Ok(());
}
- todo!()
+ Ok(())
})
}
}
+ impl<'ctx, E: $crate::effect::Effect<'ctx>, M> $crate::protocol::visitor::sequence::SequenceScope<'ctx, E> for Walker<'ctx, M> {
+ fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> {
+ E::wrap(async {
+ let mut index = 0;
+ match self.field {$(
+ field if { index += 1; field == index - 1 } => {
+ match $crate::macros::visit_tag::<{ $crate::TAG_FIELD.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::noop::NoopWalker::new()
+ ).await {
+ Ok($crate::Flow::Continue) => {},
+ _ => return Flow::Done,
+ }
+
+ match $crate::macros::visit_tag::<{ $crate::TAG_KEY.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::value::ValueWalker::new(stringify!($field))
+ ).await {
+ Ok($crate::Flow::Continue) => {},
+ Ok(_) => return Flow::Done,
+ Err(_) => unreachable!(),
+ }
+
+ let walker = $crate::Walk::<M, E>::into_walker(&self.value.$field);
+ $crate::Walker::<E>::walk(walker, visitor).await;
+ self.field += 1;
+ Flow::Continue
+ }
+ )*
+ _ => Flow::Done
+ }
+ })
+ }
+
+ fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E> {
+ const X: &[&str] = &[$(stringify!($field)),*];
+ E::ready((X.len(), Some(X.len())))
+ }
+ }
+
$crate::any::any_trait! {
- impl['a, 'ctx, E] Walker<'ctx, E> = [
+ impl['a, 'ctx, M] Walker<'ctx, M> = [
// dyn Hint<'a, 'ctx, OwnedStatic<bool>, E> + 'a,
- ] where E: $crate::effect::Effect<'ctx>
+ ]
}
};
@@ -210,16 +277,25 @@ mod test {
struct Demo {
a: bool,
b: bool,
+ other: Other,
+ }
+
+ #[derive(Walk!)]
+ struct Other {
+ value: bool,
}
#[test]
fn demo() {
- let value = Demo { a: true, b: false };
+ let value = Demo { a: true, b: false, other: Other { value: true } };
- let walker = value.into_walker::<Blocking>();
+ let walker = Walk::<DefaultMode, Blocking>::into_walker(&value);
let mut visitor = builders::debug::Visitor::<Blocking>::new();
- dbg!(Spin::block_on(walker.walk(&mut visitor)));
+ dbg!(Spin::block_on(Walker::<Blocking>::walk(
+ walker,
+ &mut visitor
+ )));
todo!();
}
diff --git a/src/macros.rs b/src/macros.rs
index a946257..ffb52b1 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -9,47 +9,51 @@ use crate::{
};
#[derive(Debug)]
-pub struct TagError {
- symbol: Symbol,
- msg: &'static str,
+pub enum TagErrorKind<E> {
+ NeverWalked,
+
+ /// This can only happen if a panic happens furing the walk and is then caught before calling
+ /// finish..
+ WalkNeverFinished,
+
+ Walker(E),
}
-impl From<TagError> for &'static str {
- fn from(value: TagError) -> Self {
- value.msg
- }
+#[derive(Debug)]
+pub struct TagError<E> {
+ symbol: Symbol,
+ err: TagErrorKind<E>,
}
-impl TagError {
- fn new<const SYMBOL: u64>(msg: &'static str) -> Self {
+impl<E> TagError<E> {
+ fn new<const SYMBOL: u64>(err: E) -> Self {
Self {
symbol: Symbol::from_int(SYMBOL),
- msg,
+ err: TagErrorKind::Walker(err),
}
}
fn never_walked<const SYMBOL: u64>() -> Self {
- Self::new::<SYMBOL>("visitor did not walk the walker")
+ Self {
+ symbol: Symbol::from_int(SYMBOL),
+ err: TagErrorKind::NeverWalked,
+ }
}
fn walk_never_finished<const SYMBOL: u64>() -> Self {
- Self::new::<SYMBOL>("walk did not finish")
+ Self {
+ symbol: Symbol::from_int(SYMBOL),
+ err: TagErrorKind::WalkNeverFinished,
+ }
}
}
-pub fn visit_tag<
- 'a,
- 'ctx: 'a,
- const SYMBOL: u64,
- E: Effect<'ctx>,
- W: Walker<'ctx, Effect = E> + 'a,
->(
+pub fn visit_tag<'a, 'ctx: 'a, const SYMBOL: u64, E: Effect<'ctx>, W: Walker<'ctx, E> + 'a>(
visitor: Visitor<'a, 'ctx>,
walker: W,
-) -> Future<'a, 'ctx, Flow<TagError>, E>
+) -> Future<'a, 'ctx, Result<Flow, TagError<W::Error>>, E>
where
W: WalkerTypes<Output = ()>,
- <W as WalkerTypes>::Error: Into<&'static str>,
{
E::wrap(async {
let result =
@@ -89,32 +93,28 @@ where
let Some(result) = result else {
// The visitor doesn't know about this tag protocol so just continue as normal.
- return Flow::Continue;
+ return Ok(Flow::Continue);
};
match result {
// The happy path.
- (Flow::Continue, Ok(_)) => Flow::Continue,
+ (Flow::Continue, Ok(_)) => Ok(Flow::Continue),
// The visitor wants to stop the control flow for some reason.
- (Flow::Break, Ok(_)) => Flow::Break,
+ (Flow::Break, Ok(_)) => Ok(Flow::Break),
+ (Flow::Done, Ok(_)) => Ok(Flow::Done),
// The walker had an error.
- (_, Err(DynWalkerError::Walker(err))) => Flow::Err(TagError::new::<SYMBOL>(err.into())),
+ (_, Err(DynWalkerError::Walker(err))) => Err(TagError::new::<SYMBOL>(err)),
// The visitor never walked the dynamic walker. Aka it didn't call walk.
- (_, Err(DynWalkerError::NeverWalked(_))) => {
- Flow::Err(TagError::never_walked::<SYMBOL>())
- }
+ (_, Err(DynWalkerError::NeverWalked(_))) => Err(TagError::never_walked::<SYMBOL>()),
// This is very hard to cause. The visitor must panic inside of .walk but then
// catch it in .visit.
(_, Err(DynWalkerError::WalkNeverFinished)) => {
- Flow::Err(TagError::walk_never_finished::<SYMBOL>())
+ Err(TagError::walk_never_finished::<SYMBOL>())
}
-
- // This isn't possible because Err(!).
- (Flow::Err(_), _) => unreachable!(),
}
})
}
diff --git a/src/protocol/visitor.rs b/src/protocol/visitor.rs
index efaa495..aad879d 100644
--- a/src/protocol/visitor.rs
+++ b/src/protocol/visitor.rs
@@ -2,3 +2,14 @@ pub mod request_hint;
pub mod sequence;
pub mod tag;
pub mod value;
+
+pub enum Status {
+ /// The protocol was used.
+ Continue,
+
+ /// The protocol was not used.
+ Skipped,
+
+ /// Should stop processing.
+ Break,
+}
diff --git a/src/protocol/visitor/request_hint.rs b/src/protocol/visitor/request_hint.rs
index f1ab735..50ae76d 100644
--- a/src/protocol/visitor/request_hint.rs
+++ b/src/protocol/visitor/request_hint.rs
@@ -1,31 +1,54 @@
-use core::ops::ControlFlow;
-
use crate::{
effect::{Effect, Future},
nameable,
- protocol::Walker,
+ never::Never,
+ protocol::{Visitor, Walker},
+ Flow,
};
/// Protocol for requesting a hint from a visitor.
-pub trait RequestHint<'ctx> {
- type Effect: Effect<'ctx>;
-
+pub trait RequestHint<'ctx, E: Effect<'ctx>> {
/// Call this to request a hint.
///
/// `walker` is what the visitor (`self`) will call to give a hint using the
/// [`Hint`][crate::builtins::walker::Hint] protocol.
- fn request_hint<'a>(
- &'a mut self,
- walker: Walker<'a, 'ctx>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
- where
- Self: 'a;
+ fn request_hint<'a>(&'a mut self, walker: Walker<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>;
}
+pub type DynRequestHint<'a, 'ctx, E> = dyn RequestHint<'ctx, E> + Send + 'a;
+
nameable! {
pub struct Name['a, 'ctx, E];
- impl [E] for dyn RequestHint<'ctx, Effect = E> + 'a where {
+ impl [E] for DynRequestHint<'a, 'ctx, E> where {
E: Effect<'ctx>,
'ctx: 'a
}
}
+
+/// Visit using the [`RequestHint`] protocol.
+///
+/// If `true` is returned then the walker should stop.
+/// This is either because of an error or the visitor is done.
+pub fn visit_request_hint<'a, 'ctx, E: Effect<'ctx>>(
+ visitor: Visitor<'a, 'ctx>,
+ walker: Walker<'a, 'ctx>,
+) -> Future<'a, 'ctx, bool, E> {
+ if let Some(object) = visitor.upcast_mut::<DynRequestHint<'_, 'ctx, E>>() {
+ // Allow the visitor to give a hint if it wants.
+ E::map(object.request_hint(walker), |flow| match flow {
+ Flow::Continue => {
+ // The visitor wants the walker to continue to it's normal
+ // walking.
+ false
+ }
+ _ => {
+ // The visitor is done (either because of an error or because
+ // it already used a hint).
+ true
+ }
+ })
+ } else {
+ // If the visitor doesn't support request hint then we continue.
+ E::ready(false)
+ }
+}
diff --git a/src/protocol/visitor/sequence.rs b/src/protocol/visitor/sequence.rs
index a3ca785..8c7b2e4 100644
--- a/src/protocol/visitor/sequence.rs
+++ b/src/protocol/visitor/sequence.rs
@@ -1,23 +1,19 @@
-use core::ops::ControlFlow;
-
use crate::{
effect::{Effect, Future},
higher_ranked_type,
hkt::AnySend,
nameable,
- protocol::{walker::hint::HintMeta, Visitor}, Flow, never::Never,
+ protocol::{walker::hint::HintMeta, Visitor},
+ Flow,
};
-pub trait Sequence<'ctx> {
- type Effect: Effect<'ctx>;
+use super::Status;
- fn visit<'a>(
- &'a mut self,
- scope: DynSequenceScope<'a, 'ctx, Self::Effect>,
- ) -> Future<'a, 'ctx, Flow<Never>, Self::Effect>;
+pub trait Sequence<'ctx, E: Effect<'ctx>> {
+ fn visit<'a>(&'a mut self, scope: DynSequenceScope<'a, 'ctx, E>) -> Future<'a, 'ctx, Flow, E>;
}
-pub type DynSequence<'a, 'ctx, E> = dyn Sequence<'ctx, Effect = E> + Send + 'a;
+pub type DynSequence<'a, 'ctx, E> = dyn Sequence<'ctx, E> + Send + 'a;
nameable! {
pub struct Name['a, 'ctx, E];
@@ -33,27 +29,13 @@ nameable! {
}
}
-pub trait SequenceScope<'ctx> {
- type Effect: Effect<'ctx>;
-
- fn size_hint<'a>(
- &'a mut self,
- ) -> Future<'a, 'ctx, (usize, Option<usize>), Self::Effect>;
+pub trait SequenceScope<'ctx, E: Effect<'ctx>> {
+ fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E>;
- fn next<'a>(
- &'a mut self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, SequenceFlow, Self::Effect>;
+ fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>;
}
-pub type DynSequenceScope<'a, 'ctx, E> = &'a mut (dyn SequenceScope<'ctx, Effect = E> + Send + 'a);
-
-#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)]
-pub enum SequenceFlow {
- Done,
- Continue,
- Break,
-}
+pub type DynSequenceScope<'a, 'ctx, E> = &'a mut (dyn SequenceScope<'ctx, E> + Send + 'a);
higher_ranked_type! {
pub type KnownHkt['ctx]: (AnySend) = for<'lt> Known
@@ -73,3 +55,27 @@ impl<'a, 'ctx: 'a, E: Effect<'ctx>> HintMeta<'ctx> for DynSequence<'a, 'ctx, E>
type Hint = Hint;
}
+
+pub fn visit_sequence<'a, 'ctx, E: Effect<'ctx>>(
+ visitor: Visitor<'a, 'ctx>,
+ scope: DynSequenceScope<'a, 'ctx, E>,
+) -> Future<'a, 'ctx, Status, E> {
+ if let Some(object) = visitor.upcast_mut::<DynSequence<'_, 'ctx, E>>() {
+ // Allow the visitor to give a hint if it wants.
+ E::map(object.visit(scope), |flow| match flow {
+ Flow::Continue => {
+ // The visitor wants the walker to continue to it's normal
+ // walking.
+ Status::Continue
+ }
+ Flow::Break | Flow::Done => {
+ // The visitor is done (either because of an error or because
+ // it already used a hint).
+ Status::Break
+ }
+ })
+ } else {
+ // If the visitor doesn't support request hint then we continue.
+ E::ready(Status::Skipped)
+ }
+}
diff --git a/src/protocol/visitor/tag.rs b/src/protocol/visitor/tag.rs
index 0ac6e5b..1be53ae 100644
--- a/src/protocol/visitor/tag.rs
+++ b/src/protocol/visitor/tag.rs
@@ -31,19 +31,15 @@ impl Kind for Dyn {
}
}
-pub trait Tag<'ctx, K: Kind> {
- type Effect: Effect<'ctx>;
-
+pub trait Tag<'ctx, K: Kind, E: Effect<'ctx>> {
fn visit<'a>(
&'a mut self,
kind: K,
- walker: DynWalker<'a, 'ctx, Self::Effect>,
- ) -> Future<'a, 'ctx, Flow<Never>, Self::Effect>
- where
- Self: 'a;
+ walker: DynWalker<'a, 'ctx, E>,
+ ) -> Future<'a, 'ctx, Flow, E>;
}
-pub type DynTag<'a, 'ctx, K, E> = dyn Tag<'ctx, K, Effect = E> + Send + 'a;
+pub type DynTag<'a, 'ctx, K, E> = dyn Tag<'ctx, K, E> + Send + 'a;
nameable! {
pub struct Name['a, 'ctx, K, E];
diff --git a/src/protocol/visitor/value.rs b/src/protocol/visitor/value.rs
index a0c435c..8e7902c 100644
--- a/src/protocol/visitor/value.rs
+++ b/src/protocol/visitor/value.rs
@@ -2,23 +2,23 @@
//!
//! In some sense, this is the most basic protocol.
-use core::ops::ControlFlow;
-
use crate::{
any::{TypeName, TypeNameable},
effect::{Effect, Future},
higher_ranked_type,
hkt::AnySend,
nameable,
- protocol::walker::hint::HintMeta,
+ never::Never,
+ protocol::{walker::hint::HintMeta, Visitor},
+ Flow,
};
+use super::Status;
+
/// Trait object for the [`Value`] protocol.
///
/// Types implementing the [`Value`] protocol will implement this trait.
-pub trait Value<'a, 'ctx: 'a, T> {
- type Effect: Effect<'ctx>;
-
+pub trait Value<'a, 'ctx: 'a, T, E: Effect<'ctx>> {
/// Visit a value of type `T`.
///
/// Use this to give a value to a visitor. Its expected that a walker
@@ -28,21 +28,21 @@ pub trait Value<'a, 'ctx: 'a, T> {
/// If a [`ControlFlow::Break`] is returned then the walker
/// should stop walking as soon as possible as there has likely been
/// and error.
- fn visit(&'a mut self, value: T) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
- where
- Self: 'a;
+ fn visit(&'a mut self, value: T) -> Future<'a, 'ctx, Flow, E>;
}
+pub type DynValue<'a, 'ctx, T, E> = dyn Value<'a, 'ctx, T, E> + Send + 'a;
+
nameable! {
pub struct Name['a, 'ctx, T, E];
- impl [T::Name, E] for dyn Value<'a, 'ctx, T, Effect = E> + 'a where {
+ impl [T::Name, E] for DynValue<'a, 'ctx, T, E> where {
T: TypeNameable<'a, 'ctx> + ?Sized,
E: Effect<'ctx>,
'ctx: 'a,
}
- impl [T, E] where dyn Value<'a, 'ctx, T::Nameable, Effect = E> + 'a {
+ impl [T, E] where DynValue<'a, 'ctx, T::Nameable, E> {
T: TypeName<'a, 'ctx> + ?Sized,
E: Effect<'ctx>,
'ctx: 'a,
@@ -54,12 +54,36 @@ higher_ranked_type! {
}
// This enrolls the Value protocol into the walker hint system.
-impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for dyn Value<'a, 'ctx, T, Effect = E> + 'a {
+impl<'a, 'ctx: 'a, T, E: Effect<'ctx>> HintMeta<'ctx> for DynValue<'a, 'ctx, T, E> {
type Known = Known<'ctx>;
type Hint = ();
}
+pub fn visit_value<'a, 'ctx, T: TypeNameable<'a, 'ctx>, E: Effect<'ctx>>(
+ visitor: Visitor<'a, 'ctx>,
+ value: T,
+) -> Future<'a, 'ctx, Status, E> {
+ if let Some(object) = visitor.upcast_mut::<DynValue<'_, 'ctx, T, E>>() {
+ // Allow the visitor to give a hint if it wants.
+ E::map(object.visit(value), |flow| match flow {
+ Flow::Continue => {
+ // The visitor wants the walker to continue to it's normal
+ // walking.
+ Status::Continue
+ }
+ Flow::Break | Flow::Done => {
+ // The visitor is done (either because of an error or because
+ // it already used a hint).
+ Status::Break
+ }
+ })
+ } else {
+ // If the visitor doesn't support request hint then we continue.
+ E::ready(Status::Skipped)
+ }
+}
+
#[cfg(test)]
mod test {
use core::{marker::PhantomData, ops::ControlFlow};
@@ -79,44 +103,40 @@ mod test {
fn visit() {
struct Visitor<E>(Option<i32>, PhantomData<fn() -> E>);
- impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, OwnedStatic<i32>> for Visitor<E>
+ impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, OwnedStatic<i32>, E> for Visitor<E>
where
E: Effect<'ctx>,
{
- type Effect = E;
-
fn visit(
&'a mut self,
OwnedStatic(value): OwnedStatic<i32>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> {
+ ) -> Future<'a, 'ctx, Flow, E> {
E::wrap(async move {
self.0 = Some(value);
- ControlFlow::Continue(())
+ Flow::Continue
})
}
}
- impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>> for Visitor<E>
+ impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, E> for Visitor<E>
where
E: Effect<'ctx>,
{
- type Effect = E;
-
fn visit(
&'a mut self,
BorrowedStatic(value): BorrowedStatic<'ctx, i32>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> {
+ ) -> Future<'a, 'ctx, Flow, E> {
E::wrap(async {
self.0 = Some(*value);
- ControlFlow::Continue(())
+ Flow::Continue
})
}
}
any_trait! {
impl['a, 'ctx, E] Visitor<E> = [
- dyn Value<'a, 'ctx, OwnedStatic<i32>, Effect = E> + 'a,
- dyn Value<'a, 'ctx, BorrowedStatic<'ctx, i32>, Effect = E> + 'a,
+ DynValue<'a, 'ctx, OwnedStatic<i32>, E>,
+ DynValue<'a, 'ctx, BorrowedStatic<'ctx, i32>, E>,
] where E: Effect<'ctx>,
}
@@ -124,7 +144,7 @@ mod test {
let object: &mut (dyn AnyTrait<'_> + Send) = &mut v;
Spin::block_on(
object
- .upcast_mut::<dyn Value<'_, '_, OwnedStatic<i32>, Effect = Blocking>>()
+ .upcast_mut::<DynValue<'_, '_, OwnedStatic<i32>, Blocking>>()
.unwrap()
.visit(OwnedStatic(42)),
);
@@ -134,7 +154,7 @@ mod test {
let object: &mut (dyn AnyTrait<'_> + Send) = &mut v;
Spin::block_on(
object
- .upcast_mut::<dyn Value<'_, '_, BorrowedStatic<'_, i32>, Effect = Blocking>>()
+ .upcast_mut::<DynValue<'_, '_, BorrowedStatic<'_, i32>, Blocking>>()
.unwrap()
.visit(BorrowedStatic(&101)),
);
@@ -146,27 +166,25 @@ mod test {
fn visit_borrowed() {
struct Visitor<'ctx, E>(Option<&'ctx mut String>, PhantomData<fn() -> E>);
- impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>> for Visitor<'ctx, E>
+ impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, E> for Visitor<'ctx, E>
where
E: Effect<'ctx>,
{
- type Effect = E;
-
fn visit(
&'a mut self,
BorrowedMutStatic(value): BorrowedMutStatic<'ctx, String>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> {
+ ) -> Future<'a, 'ctx, Flow, E> {
E::wrap(async {
self.0 = Some(value);
- ControlFlow::Continue(())
+ Flow::Continue
})
}
}
any_trait! {
impl['a, 'ctx, E] Visitor<'ctx, E> = [
- dyn Value<'a, 'ctx, BorrowedMutStatic<'ctx, String>, Effect = E> + 'a,
+ DynValue<'a, 'ctx, BorrowedMutStatic<'ctx, String>, E>,
] where E: Effect<'ctx>
}
@@ -176,7 +194,7 @@ mod test {
let object: &mut (dyn AnyTrait<'_> + Send) = &mut v;
Spin::block_on(
object
- .upcast_mut::<dyn Value<'_, '_, _, Effect = Blocking>>()
+ .upcast_mut::<DynValue<'_, '_, _, Blocking>>()
.unwrap()
.visit(BorrowedMutStatic(&mut y)),
);
@@ -189,26 +207,24 @@ mod test {
fn visit_borrowed_unsized() {
struct Visitor<'ctx, E>(Option<&'ctx str>, PhantomData<fn() -> E>);
- impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, str>> for Visitor<'ctx, E>
+ impl<'a, 'ctx: 'a, E> Value<'a, 'ctx, BorrowedStatic<'ctx, str>, E> for Visitor<'ctx, E>
where
E: Effect<'ctx>,
{
- type Effect = E;
-
fn visit(
&'a mut self,
BorrowedStatic(value): BorrowedStatic<'ctx, str>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> {
+ ) -> Future<'a, 'ctx, Flow, E> {
E::wrap(async {
self.0 = Some(value);
- ControlFlow::Continue(())
+ Flow::Continue
})
}
}
any_trait! {
impl['a, 'ctx, E] Visitor<'ctx, E> = [
- dyn Value<'a, 'ctx, BorrowedStatic<'ctx, str>, Effect = E> + 'a,
+ DynValue<'a, 'ctx, BorrowedStatic<'ctx, str>, E>,
] where E: Effect<'ctx>
}
@@ -218,7 +234,7 @@ mod test {
let object: &mut (dyn AnyTrait<'_> + Send) = &mut v;
Spin::block_on(
object
- .upcast_mut::<dyn Value<'_, '_, BorrowedStatic<'_, str>, Effect = Blocking> + '_>()
+ .upcast_mut::<DynValue<'_, '_, BorrowedStatic<'_, str>, Blocking>>()
.unwrap()
.visit(BorrowedStatic(&y)),
);
diff --git a/src/transform.rs b/src/transform.rs
index 2e3d14b..9d696be 100644
--- a/src/transform.rs
+++ b/src/transform.rs
@@ -5,13 +5,7 @@ use crate::{
};
#[inline]
-pub fn transform<
- 'a,
- 'ctx,
- B: Builder<'ctx, Effect = E> + 'a,
- W: Walker<'ctx, Effect = E> + 'a,
- E: Effect<'ctx>,
->(
+pub fn transform<'a, 'ctx, B: Builder<'ctx, E> + 'a, W: Walker<'ctx, E> + 'a, E: Effect<'ctx>>(
seed: B::Seed,
walker: W,
) -> Future<'a, 'ctx, (Result<B::Value, B::Error>, Result<W::Output, W::Error>), E> {
diff --git a/src/walk.rs b/src/walk.rs
index 32232fd..0dbccee 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -1,23 +1,17 @@
pub mod walkers;
-use core::ops::ControlFlow;
-
use crate::{
effect::{Effect, Future},
protocol::Visitor,
+ Flow,
};
/// A type that can be walked.
-pub trait Walk<'ctx>: WalkerTypes + Sized {
+pub trait Walk<'ctx, M, E: Effect<'ctx>>: WalkerTypes + Sized {
/// The walker for the type.
- type Walker<E: Effect<'ctx>>: Walker<
- 'ctx,
- Error = Self::Error,
- Output = Self::Output,
- Effect = E,
- >;
-
- fn into_walker<E: Effect<'ctx>>(self) -> Self::Walker<E>;
+ type Walker: Walker<'ctx, E, Error = Self::Error, Output = Self::Output>;
+
+ fn into_walker(self) -> Self::Walker;
}
pub trait WalkerTypes {
@@ -38,40 +32,34 @@ pub trait WalkerTypes {
/// - Call [From::from()] with a value to be walked to make a walker.
/// - Call [Self::walk()] to walk the value. Data will be sent to the provided
/// visitor.
-pub trait Walker<'ctx>: WalkerTypes + Send {
- type Effect: Effect<'ctx>;
-
+pub trait Walker<'ctx, E: Effect<'ctx>>: WalkerTypes + Send {
/// Walk the value.
///
/// The walker should send data to the `visitor` as it walks the value.
fn walk<'a>(
self,
visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
+ ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
where
Self: 'a;
}
-pub trait WalkerObjSafe<'ctx>: Send {
- type Effect: Effect<'ctx>;
-
- fn walk<'a>(
- &'a mut self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+pub trait WalkerObjSafe<'ctx, E: Effect<'ctx>>: Send {
+ fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a;
fn skip(&mut self);
}
-pub type DynWalker<'a, 'ctx, E> = &'a mut (dyn WalkerObjSafe<'ctx, Effect = E> + Send + 'a);
+pub type DynWalker<'a, 'ctx, E> = &'a mut (dyn WalkerObjSafe<'ctx, E> + Send + 'a);
enum DynWalkerState<W: WalkerTypes> {
Skipped,
Walking,
Pending(W),
- Done(Result<W::Output, W::Error>),
+ Done(W::Output),
+ Err(W::Error),
}
pub enum DynWalkerError<W: WalkerTypes> {
@@ -100,31 +88,39 @@ impl<W: WalkerTypes> DynWalkerAdapter<W> {
DynWalkerState::Skipped => Ok(None),
DynWalkerState::Walking => Err(DynWalkerError::WalkNeverFinished),
DynWalkerState::Pending(walker) => Err(DynWalkerError::NeverWalked(walker)),
- DynWalkerState::Done(result) => result.map(Some).map_err(DynWalkerError::Walker),
+ DynWalkerState::Done(value) => Ok(Some(value)),
+ DynWalkerState::Err(err) => Err(DynWalkerError::Walker(err)),
}
}
}
-impl<'ctx, W: Walker<'ctx>> WalkerObjSafe<'ctx> for DynWalkerAdapter<W> {
- type Effect = W::Effect;
-
- fn walk<'a>(
- &'a mut self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, ControlFlow<(), ()>, Self::Effect>
+impl<'ctx, W: Walker<'ctx, E>, E: Effect<'ctx>> WalkerObjSafe<'ctx, E> for DynWalkerAdapter<W> {
+ fn walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E>
where
Self: 'a,
{
- Self::Effect::wrap(async {
+ E::wrap(async {
if let DynWalkerState::Pending(walker) =
core::mem::replace(&mut self.state, DynWalkerState::Walking)
{
// Walk the walker.
- self.state = DynWalkerState::Done(walker.walk(visitor).await);
+ match walker.walk(visitor).await {
+ Ok(value) => {
+ self.state = DynWalkerState::Done(value);
+ Flow::Continue
+ }
+ 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::Break
+ }
+ }
} else {
// Can't do anything if the walker has already been walked.
+ Flow::Continue
}
- ControlFlow::Continue(())
})
}
diff --git a/src/walk/walkers/core.rs b/src/walk/walkers/core.rs
index 734a5c6..172244d 100644
--- a/src/walk/walkers/core.rs
+++ b/src/walk/walkers/core.rs
@@ -1,4 +1,6 @@
// pub mod array;
pub mod bool;
+pub mod noop;
pub mod tag;
+pub mod value;
diff --git a/src/walk/walkers/core/array.rs b/src/walk/walkers/core/array.rs
index c4b9568..cc3a6da 100644
--- a/src/walk/walkers/core/array.rs
+++ b/src/walk/walkers/core/array.rs
@@ -2,12 +2,6 @@ use core::{mem::MaybeUninit, ops::ControlFlow};
use crate::{
any_trait,
- effect::{Effect, SyncEffect, Yield},
- protocol::{
- visitor::{RequestHint, Sequence, SequenceScope, Status},
- walker::{Hint, HintMeta},
- Visitor,
- },
};
impl<'ctx, T: crate::Walk<'ctx>, const N: usize> crate::Walk<'ctx> for [T; N]
diff --git a/src/walk/walkers/core/bool.rs b/src/walk/walkers/core/bool.rs
index 24bb421..a3f2a93 100644
--- a/src/walk/walkers/core/bool.rs
+++ b/src/walk/walkers/core/bool.rs
@@ -1,55 +1,29 @@
-use crate::{any::static_wrapper::OwnedStatic, protocol::visitor::value::Value};
-use core::{marker::PhantomData, mem::MaybeUninit, ops::ControlFlow};
+use crate::{effect::Effect, Walk, WalkerTypes};
-use crate::{
- any_trait,
- effect::{Effect, Future},
- protocol::{
- walker::hint::{Hint, HintMeta},
- Visitor,
- },
-};
+use super::value::{ValueWalker, BorrowWalker};
-impl<'ctx> crate::Walk<'ctx> for bool {
- type Walker<E: Effect<'ctx>> = Walker<E>;
+impl<'ctx, M, E: Effect<'ctx>> Walk<'ctx, M, E> for bool {
+ type Walker = ValueWalker<bool>;
- fn into_walker<E: Effect<'ctx>>(self) -> Self::Walker<E> {
- Walker(self, PhantomData)
+ fn into_walker(self) -> Self::Walker {
+ ValueWalker::new(self)
}
}
-pub struct Walker<E>(bool, PhantomData<fn() -> E>);
-
-impl crate::WalkerTypes for bool {
- type Error = ();
-
- type Output = ();
+impl WalkerTypes for bool {
+ type Error = <ValueWalker<bool> as WalkerTypes>::Error;
+ type Output = <ValueWalker<bool> as WalkerTypes>::Output;
}
-impl<E> crate::WalkerTypes for Walker<E> {
- type Error = ();
+impl<'ctx, M, E: Effect<'ctx>> Walk<'ctx, M, E> for &'ctx bool {
+ type Walker = ValueWalker<bool>;
- type Output = ();
+ fn into_walker(self) -> Self::Walker {
+ ValueWalker::new(*self)
+ }
}
-impl<'ctx, E: Effect<'ctx>> crate::Walker<'ctx> for Walker<E> {
- type Effect = E;
- #[inline]
- fn walk<'a>(
- self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
- where
- 'ctx: 'a,
- {
- E::wrap(async move {
- if let Some(object) =
- visitor.upcast_mut::<dyn Value<'_, 'ctx, OwnedStatic<bool>, Effect = E> + '_>()
- {
- object.visit(OwnedStatic(self.0)).await;
- }
-
- Ok(())
- })
- }
+impl<'ctx> WalkerTypes for &'ctx bool {
+ type Error = <ValueWalker<bool> as WalkerTypes>::Error;
+ type Output = <ValueWalker<bool> as WalkerTypes>::Output;
}
diff --git a/src/walk/walkers/core/noop.rs b/src/walk/walkers/core/noop.rs
new file mode 100644
index 0000000..03b4b7c
--- /dev/null
+++ b/src/walk/walkers/core/noop.rs
@@ -0,0 +1,36 @@
+use crate::{
+ effect::{Effect, Future},
+ never::Never,
+ protocol::Visitor,
+ WalkerTypes,
+};
+
+/// A walker that does nothing.
+///
+/// This walker is useful for tags that don't need a value.
+#[non_exhaustive]
+pub struct NoopWalker;
+
+impl NoopWalker {
+ pub fn new() -> Self {
+ Self
+ }
+}
+
+impl WalkerTypes for NoopWalker {
+ type Error = Never;
+
+ type Output = ();
+}
+
+impl<'ctx, E: Effect<'ctx>> crate::Walker<'ctx, E> for NoopWalker {
+ fn walk<'a>(
+ self,
+ _visitor: Visitor<'a, 'ctx>,
+ ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
+ where
+ Self: 'a,
+ {
+ E::ready(Ok(()))
+ }
+}
diff --git a/src/walk/walkers/core/tag.rs b/src/walk/walkers/core/tag.rs
index 8c40f2d..5c5d144 100644
--- a/src/walk/walkers/core/tag.rs
+++ b/src/walk/walkers/core/tag.rs
@@ -2,268 +2,110 @@ use core::{any::TypeId, marker::PhantomData};
use crate::{
any::static_wrapper::OwnedStatic,
+ any_trait,
effect::{Effect, Future},
+ macros::{visit_tag, TagError},
+ never::Never,
protocol::{
- visitor::{sequence::{DynSequence, SequenceScope, SequenceFlow}, value::Value, tag::DynTag},
+ visitor::{
+ request_hint::{visit_request_hint, DynRequestHint, RequestHint},
+ sequence::{DynSequence, SequenceScope},
+ tag::DynTag,
+ Status,
+ value::{visit_value, DynValue, Value},
+ },
Visitor,
},
- WalkerTypes, Flow, macros::{visit_tag, TagError}, TAG_FIELD_NAMES, TAG_SEQ_INDEX, never::Never, TAG_SEQ_LEN,
+ Flow, WalkerTypes, TAG_FIELD_NAMES, TAG_SEQ_INDEX, TAG_SEQ_LEN,
};
-pub struct ValueWalker<T, E>(T, PhantomData<fn() -> E>);
+use super::value::ValueWalker;
-impl<T, E> ValueWalker<T, E> {
- pub fn new(value: T) -> Self {
- Self(value, PhantomData)
- }
-}
-
-pub struct MissingProtocol(pub &'static str);
-
-impl From<MissingProtocol> for &'static str {
- fn from(value: MissingProtocol) -> Self {
- value.0
- }
-}
-
-impl<T: Send, E> WalkerTypes for ValueWalker<T, E> {
- type Error = MissingProtocol;
-
- type Output = ();
-}
-
-impl<'ctx, T: Send + 'static, E: Effect<'ctx>> crate::Walker<'ctx> for ValueWalker<T, E> {
- type Effect = E;
-
- fn walk<'a>(
- self,
- visitor: crate::protocol::Visitor<'a, 'ctx>,
- ) -> crate::effect::Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
- where
- Self: 'a,
- {
- E::wrap(async {
- // We don't need to request a hint because we always just visit a static string.
- if let Some(object) = visitor
- .upcast_mut::<dyn Value<'_, 'ctx, OwnedStatic<T>, Effect = E> + '_>()
- {
- // Visit with the name.
- object.visit(OwnedStatic(self.0)).await;
-
- Ok(())
- } else {
- Err(MissingProtocol(
- "visitor missing protocol Value<?>",
- ))
- }
- })
- }
-}
-
-pub struct NamesWalker<E> {
- names: &'static [&'static str],
+pub struct StaticSliceWalker<T: 'static, W> {
+ names: &'static [T],
current: usize,
- error: Option<(usize, WithTagError<MissingProtocol>)>,
- _marker: PhantomData<fn() -> E>,
+ _marker: PhantomData<fn() -> W>,
}
-impl<E> NamesWalker<E> {
- pub fn new(names: &'static [&'static str]) -> Self {
+impl<T, W> StaticSliceWalker<T, W> {
+ pub fn new(names: &'static [T]) -> Self {
Self {
names,
current: 0,
- error: None,
_marker: PhantomData,
}
}
}
-pub enum SequenceError<E, I> {
- Err(E),
- Tag(TagError),
- Item(usize, I),
-}
-
-impl<E: Into<&'static str>, I: Into<&'static str>> From<SequenceError<E, I>> for &'static str {
- fn from(value: SequenceError<E, I>) -> Self {
- match value {
- SequenceError::Err(err) => err.into(),
- SequenceError::Item(_, err) => err.into(),
- SequenceError::Tag(err) => err.into(),
- }
- }
-}
-
-impl<E> WalkerTypes for NamesWalker<E> {
- type Error = SequenceError<MissingProtocol, WithTagError<MissingProtocol>>;
+impl<T, W> WalkerTypes for StaticSliceWalker<T, W> {
+ type Error = TagError<Never>;
type Output = ();
}
-impl<'ctx, E: Effect<'ctx>> crate::Walker<'ctx> for NamesWalker<E> {
- type Effect = E;
-
+impl<'ctx, T, W, E> crate::Walker<'ctx, E> for StaticSliceWalker<T, W>
+where
+ E: Effect<'ctx>,
+ W: crate::Walker<'ctx, E> + WalkerTypes<Output = ()>,
+ T: Sync,
+ &'static T: Into<W>,
+{
fn walk<'a>(
mut self,
visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
+ ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
where
Self: 'a,
{
E::wrap(async move {
- match visit_tag::<{ TAG_SEQ_LEN.to_int() }, Self::Effect, _>(
- visitor,
- ValueWalker::new(self.names.len())
- ).await {
- Flow::Continue => {},
- Flow::Break => return Ok(()),
- Flow::Err(err) => return Err(SequenceError::Tag(err)),
+ if visit_request_hint::<E>(visitor, &mut self).await {
+ return Ok(());
+ }
+
+ if matches!(
+ visit_value::<_, E>(visitor, OwnedStatic(self.names)).await,
+ Status::Break | Status::Continue
+ ) {
+ return Ok(());
}
- // We don't need to request a hint because we always just visit a sequence.
if let Some(object) = visitor.upcast_mut::<DynSequence<'_, 'ctx, E>>() {
// Visit with the name. Ignore the flow because we return a result not a flow.
let _ = object.visit(&mut self).await;
-
- // Check if any items had errors.
- match self.error {
- Some((index, err)) => Err(SequenceError::Item(index, err)),
- None => Ok(()),
- }
- } else {
- Err(SequenceError::Err(MissingProtocol("visitor missing protocol Sequence")))
}
+
+ Ok(())
})
}
}
-impl<'ctx, E: Effect<'ctx>> SequenceScope<'ctx> for NamesWalker<E> {
- type Effect = E;
+any_trait! {
+ impl['a, 'ctx, T, W] StaticSliceWalker<T, W> = [
+ ]
+}
- fn next<'a>(
- &'a mut self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, SequenceFlow, Self::Effect> {
+impl<'ctx, T, W, E> SequenceScope<'ctx, E> for StaticSliceWalker<T, W>
+where
+ E: Effect<'ctx>,
+ W: crate::Walker<'ctx, E> + WalkerTypes<Output = ()>,
+ T: Sync,
+ &'static T: Into<W>,
+{
+ fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> {
if let Some(name) = self.names.get(self.current) {
- let current = self.current;
self.current += 1;
E::wrap(async move {
- match crate::Walker::walk(SeqItemWalker::new(current, ValueWalker::<_, E>::new(*name)), visitor).await {
- Ok(()) => SequenceFlow::Continue,
- Err(err) => {
- self.error = Some((self.current, err));
- SequenceFlow::Break
- },
+ match crate::Walker::walk(name.into(), visitor).await {
+ Ok(()) => Flow::Continue,
+ Err(_) => unreachable!(),
}
})
} else {
- E::ready(SequenceFlow::Done)
+ E::ready(Flow::Done)
}
}
- fn size_hint<'a>(
- &'a mut self,
- ) -> Future<'a, 'ctx, (usize, Option<usize>), Self::Effect> {
+ fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E> {
E::ready((self.names.len(), Some(self.names.len())))
}
-
-}
-
-pub struct SeqItemWalker<W> {
- walker: W,
- index: usize,
-}
-
-impl<W> SeqItemWalker<W> {
- pub fn new(index: usize, walker: W) -> Self {
- Self {
- walker,
- index,
- }
- }
-}
-
-pub enum WithTagError<E> {
- Tag(TagError),
- Err(E),
-}
-
-impl<E: Into<&'static str>> From<WithTagError<E>> for &'static str {
- fn from(value: WithTagError<E>) -> Self {
- match value {
- WithTagError::Tag(value) => value.into(),
- WithTagError::Err(value) => value.into(),
- }
- }
-}
-
-impl<W: WalkerTypes> WalkerTypes for SeqItemWalker<W> {
- type Error = WithTagError<W::Error>;
-
- type Output = ();
-}
-
-impl<'ctx, W: crate::Walker<'ctx> + WalkerTypes<Output = ()>> crate::Walker<'ctx> for SeqItemWalker<W> {
- type Effect = W::Effect;
-
- fn walk<'a>(
- self,
- visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
- where
- Self: 'a,
- {
- Self::Effect::wrap(async move {
- match visit_tag::<{ TAG_SEQ_INDEX.to_int() }, Self::Effect, _>(
- visitor,
- ValueWalker::new(self.index)
- ).await {
- Flow::Continue => {},
- Flow::Break => return Ok(()),
- Flow::Err(err) => return Err(WithTagError::Tag(err)),
- }
-
- self.walker.walk(visitor).await.map_err(WithTagError::Err)
- })
- }
-}
-
-pub struct NoopWalker<E> {
- _marker: PhantomData<fn() -> E>
-}
-
-impl<E> NoopWalker<E> {
- pub fn new() -> Self {
- Self {
- _marker: PhantomData
- }
- }
-}
-
-pub enum NoopError {}
-
-impl From<NoopError> for &'static str {
- fn from(value: NoopError) -> Self {
- match value {}
- }
-}
-
-impl<E> WalkerTypes for NoopWalker<E> {
- type Error = NoopError;
-
- type Output = ();
-}
-
-impl<'ctx, E: Effect<'ctx>> crate::Walker<'ctx> for NoopWalker<E> {
- type Effect = E;
-
- fn walk<'a>(
- self,
- _visitor: Visitor<'a, 'ctx>,
- ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
- where
- Self: 'a,
- {
- E::ready(Ok(()))
- }
}
diff --git a/src/walk/walkers/core/value.rs b/src/walk/walkers/core/value.rs
new file mode 100644
index 0000000..4f75750
--- /dev/null
+++ b/src/walk/walkers/core/value.rs
@@ -0,0 +1,89 @@
+use crate::{
+ any::static_wrapper::{BorrowedStatic, OwnedStatic},
+ effect::{Effect, Future},
+ never::Never,
+ protocol::{visitor::value::visit_value, Visitor},
+ WalkerTypes,
+};
+
+/// A very basic walker that uses the [`Value`][crate::protocol::visitor::value::Value] protocol.
+///
+/// Primitive types use this walker as their main walker.
+/// This walker doesn't consider it an error if the visitor doesn't have the protocol.
+pub struct ValueWalker<T>(T);
+
+impl<T> ValueWalker<T> {
+ /// Create walker from a value.
+ pub fn new(value: T) -> Self {
+ Self(value)
+ }
+}
+
+impl<T> From<T> for ValueWalker<T> {
+ fn from(value: T) -> Self {
+ Self::new(value)
+ }
+}
+
+impl<T: Copy> From<&T> for ValueWalker<T> {
+ fn from(value: &T) -> Self {
+ Self::new(*value)
+ }
+}
+
+impl<T> WalkerTypes for ValueWalker<T> {
+ type Error = Never;
+
+ type Output = ();
+}
+
+impl<'ctx, T: Send + 'static, E: Effect<'ctx>> crate::Walker<'ctx, E> for ValueWalker<T> {
+ fn walk<'a>(
+ self,
+ visitor: Visitor<'a, 'ctx>,
+ ) -> Future<'a, 'ctx, 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(()),
+ )
+ }
+}
+
+/// Borrowed form of [`ValueWalker`].
+///
+/// This walker supports values borrowed for `'ctx` or longer.
+pub struct BorrowWalker<'ctx, T: ?Sized>(&'ctx T);
+
+impl<'ctx, T: ?Sized> BorrowWalker<'ctx, T> {
+ /// Create walker from a value.
+ pub fn new(value: &'ctx T) -> Self {
+ Self(value)
+ }
+}
+
+impl<'ctx, T: ?Sized> WalkerTypes for BorrowWalker<'ctx, T> {
+ type Error = Never;
+
+ type Output = ();
+}
+
+impl<'ctx, T: ?Sized + Sync + 'static, E: Effect<'ctx>> crate::Walker<'ctx, E>
+ for BorrowWalker<'ctx, T>
+{
+ fn walk<'a>(
+ self,
+ visitor: Visitor<'a, 'ctx>,
+ ) -> Future<'a, 'ctx, 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(())
+ })
+ }
+}