Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs153
1 files changed, 56 insertions, 97 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 753ac7c..03b2e0d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -28,11 +28,15 @@ use core::ops::ControlFlow;
pub use build::*;
use effect::{Effect, Future};
+use macros::TagError;
use protocol::Visitor;
use symbol::Symbol;
pub use transform::*;
pub use walk::*;
+// #[doc(hidden)]
+pub mod macros;
+
pub mod never {
mod sealed {
pub trait Extract {
@@ -52,10 +56,26 @@ 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_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_ENUM: Symbol = Symbol::new("Enum");
#[derive(Debug)]
pub enum StructWalkError {
- Tag(Symbol, &'static str),
+ Tag(TagError),
+}
+
+#[must_use]
+pub enum Flow<Error> {
+ /// Processing should continue as normal.
+ Continue,
+
+ /// Processing should stop, but there is no direct error to report.
+ Break,
+
+ /// Processing should stop with this error.
+ Err(Error),
}
#[macro_export]
@@ -78,7 +98,7 @@ macro_rules! Walk {
}
}
- impl<'ctx> $crate::WalkerTypes<'ctx> for &'ctx $name {
+ impl<'ctx> $crate::WalkerTypes for &'ctx $name {
type Error = $crate::StructWalkError;
type Output = ();
}
@@ -88,7 +108,7 @@ macro_rules! Walk {
_marker: ::core::marker::PhantomData<fn() -> E>,
}
- impl<'ctx, E> $crate::WalkerTypes<'ctx> for Walker<'ctx, E> {
+ impl<'ctx, E> $crate::WalkerTypes for Walker<'ctx, E> {
type Error = $crate::StructWalkError;
type Output = ();
}
@@ -126,52 +146,42 @@ macro_rules! Walk {
// - Tagged: struct field names
// - Sequence: the fields
- if let Ok((result, flow)) =
- $crate::try_visit_tag::<{ $crate::TAG_TYPE_NAME.to_int() }, E, _>(
- visitor,
- $crate::walkers::core::tag::NameWalker::new(stringify!($name))
- ).await
- {
- match result {
- Ok(()) => {},
- Err($crate::DynWalkerError::Walker($crate::walkers::core::tag::MissingProtocol(msg))) => {
- return Err($crate::StructWalkError::Tag($crate::TAG_TYPE_NAME, msg))
- }
- Err($crate::DynWalkerError::NeverWalked(_)) => {
- return Err($crate::StructWalkError::Tag($crate::TAG_TYPE_NAME, "visitor didn't walk walker"))
- },
- Err($crate::DynWalkerError::WalkNeverFinished) => {
- return Err($crate::StructWalkError::Tag($crate::TAG_TYPE_NAME, "walk didn't finish"))
- },
- }
+ match $crate::macros::visit_tag::<{ $crate::TAG_STRUCT.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::tag::NoopWalker::new()
+ ).await {
+ $crate::Flow::Continue => {},
+ $crate::Flow::Break => return Ok(()),
+ $crate::Flow::Err(_) => unreachable!(),
+ }
- if let ::core::ops::ControlFlow::Break(()) = flow {
- return Ok(());
- }
+ match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_NAME.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::tag::ValueWalker::new(stringify!($name))
+ ).await {
+ $crate::Flow::Continue => {},
+ $crate::Flow::Break => return Ok(()),
+ $crate::Flow::Err(err) => return Err(StructWalkError::Tag(err)),
}
- if let Ok((result, flow)) =
- $crate::try_visit_tag::<{ $crate::TAG_TYPE_ID.to_int() }, E, _>(
- visitor,
- $crate::walkers::core::tag::TypeIdWalker::new::<$name>()
- ).await
- {
- match result {
- Ok(()) => {},
- Err($crate::DynWalkerError::Walker($crate::walkers::core::tag::MissingProtocol(msg))) => {
- return Err($crate::StructWalkError::Tag($crate::TAG_TYPE_ID, msg))
- }
- Err($crate::DynWalkerError::NeverWalked(_)) => {
- return Err($crate::StructWalkError::Tag($crate::TAG_TYPE_ID, "visitor didn't walk walker"))
- },
- Err($crate::DynWalkerError::WalkNeverFinished) => {
- return Err($crate::StructWalkError::Tag($crate::TAG_TYPE_ID, "walk didn't finish"))
- },
- }
+ match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_ID.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::tag::ValueWalker::new(::core::any::TypeId::of::<$name>())
+ ).await {
+ $crate::Flow::Continue => {},
+ $crate::Flow::Break => return Ok(()),
+ $crate::Flow::Err(err) => return Err(StructWalkError::Tag(err)),
+ }
- if let ::core::ops::ControlFlow::Break(()) = flow {
- return Ok(());
- }
+ match $crate::macros::visit_tag::<{ $crate::TAG_FIELD_NAMES.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::tag::NamesWalker::new(&[$(
+ stringify!($field)
+ ),*])
+ ).await {
+ $crate::Flow::Continue => {},
+ $crate::Flow::Break => return Ok(()),
+ $crate::Flow::Err(err) => return Err(StructWalkError::Tag(err)),
}
todo!()
@@ -189,57 +199,6 @@ macro_rules! Walk {
};
}
-pub fn try_visit_tag<
- 'a,
- 'ctx,
- const SYMBOL: u64,
- E: Effect<'ctx>,
- W: Walker<'ctx, Effect = E> + 'a,
->(
- visitor: Visitor<'a, 'ctx>,
- walker: W,
-) -> Future<
- 'a,
- 'ctx,
- Result<
- (
- Result<W::Output, DynWalkerError<'ctx, W>>,
- ControlFlow<(), protocol::visitor::tag::Status>,
- ),
- W,
- >,
- E,
-> {
- E::wrap(async {
- if let Some(object) = visitor.upcast_mut::<
- dyn protocol::visitor::tag::Tag<
- 'ctx,
- protocol::visitor::tag::Const<SYMBOL>,
- Effect = E
- > + '_
- >() {
- let mut name_walker = DynWalkerAdapter::new(walker);
- let flow = object.visit(protocol::visitor::tag::Const, &mut name_walker).await;
- Ok((name_walker.finish(), match flow {
- ControlFlow::Continue(()) => ControlFlow::Continue(protocol::visitor::tag::Status::Walked),
- ControlFlow::Break(()) => ControlFlow::Break(()),
- }))
- } else if let Some(object) = visitor.upcast_mut::<
- dyn protocol::visitor::tag::Tag<
- 'ctx,
- protocol::visitor::tag::Dyn,
- Effect = E
- > + '_
- >() {
- let mut name_walker = DynWalkerAdapter::new(walker);
- let flow = object.visit(protocol::visitor::tag::Dyn(Symbol::from_int(SYMBOL)), &mut name_walker).await;
- Ok((name_walker.finish(), flow))
- } else {
- Err(walker)
- }
- })
-}
-
#[cfg(test)]
mod test {
use crate::effect::{BlockOn, Blocking, Spin};
@@ -258,7 +217,7 @@ mod test {
let value = Demo { a: true, b: false };
let walker = value.into_walker::<Blocking>();
- let mut visitor = builders::debug::Walker::<Blocking>::new();
+ let mut visitor = builders::debug::Visitor::<Blocking>::new();
dbg!(Spin::block_on(walker.walk(&mut visitor)));