Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 153 |
1 files changed, 56 insertions, 97 deletions
@@ -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))); |