Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs81
1 files changed, 50 insertions, 31 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c1709cc..7733233 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -28,8 +28,7 @@ use core::ops::ControlFlow;
pub use build::*;
use effect::{Effect, Future};
-use macros::TagError;
-use protocol::Visitor;
+use protocol::{Visitor, visitor::tag::TagError};
use symbol::Symbol;
pub use transform::*;
pub use walk::*;
@@ -60,6 +59,8 @@ 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_MAP: Symbol = Symbol::new("Map");
+pub const TAG_SEQ: Symbol = Symbol::new("Sequence");
pub const TAG_FIELD: Symbol = Symbol::new("Field");
pub const TAG_ENUM: Symbol = Symbol::new("Enum");
@@ -68,6 +69,7 @@ pub enum DefaultMode {}
#[derive(Debug)]
pub enum StructWalkError {
Tag(TagError<never::Never>),
+ FieldTag(TagError<TagError<never::Never>>),
}
#[must_use]
@@ -146,12 +148,6 @@ macro_rules! Walk {
}
}
- // Follow the standard set of protocols for a struct.
- // - Tagged: struct name
- // - Tagged: struct type
- // - Tagged: struct field names
- // - Sequence: the fields
-
// Attempt to visit the value directly.
if !matches!($crate::protocol::visitor::value::visit_value::<_, E>(
visitor,
@@ -160,48 +156,67 @@ macro_rules! Walk {
return Ok(());
}
+ // Follow the standard set of protocols for a struct.
+ // - Tagged: struct name
+ // - Tagged: struct type
+ // - Tagged: struct field names
+ // - Sequence: the fields
+
// Describe the struct in a general way:
+ use $crate::protocol::visitor::Status as S;
+
// Give the type ID
- match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_ID.to_int() }, E, _>(
+ match $crate::protocol::visitor::tag::visit_tag::<{ $crate::TAG_TYPE_ID.to_int() }, E, _>(
visitor,
$crate::walkers::core::value::ValueWalker::new(::core::any::TypeId::of::<$name>())
).await {
- Ok($crate::Flow::Continue) => {},
- Ok(_) => return Ok(()),
- Err(_) => unreachable!(),
+ Ok(S::Skipped) | Ok(S::Continue) => {},
+ Ok(S::Break) => return Ok(()),
+ Err(err) => return Err(StructWalkError::Tag(err)),
}
// Signal this is a struct.
- match $crate::macros::visit_tag::<{ $crate::TAG_STRUCT.to_int() }, E, _>(
+ match $crate::protocol::visitor::tag::visit_tag::<{ $crate::TAG_STRUCT.to_int() }, E, _>(
visitor,
$crate::walkers::core::noop::NoopWalker::new()
).await {
- Ok($crate::Flow::Continue) => {},
- _ => return Ok(()),
+ Ok(S::Skipped) => {
+ // If can't tag as a struct try as a map.
+ match $crate::protocol::visitor::tag::visit_tag::<{ $crate::TAG_MAP.to_int() }, E, _>(
+ visitor,
+ $crate::walkers::core::noop::NoopWalker::new()
+ ).await {
+ Ok(S::Skipped) | Ok(S::Continue) => {},
+ Ok(S::Break) => return Ok(()),
+ Err(err) => return Err(StructWalkError::Tag(err)),
+ }
+ },
+ Ok(S::Continue) => {},
+ Ok(S::Break) => return Ok(()),
+ Err(err) => return Err(StructWalkError::Tag(err)),
}
// Give the type name.
- match $crate::macros::visit_tag::<{ $crate::TAG_TYPE_NAME.to_int() }, E, _>(
+ match $crate::protocol::visitor::tag::visit_tag::<{ $crate::TAG_TYPE_NAME.to_int() }, E, _>(
visitor,
$crate::walkers::core::value::ValueWalker::new(stringify!($name))
).await {
- Ok($crate::Flow::Continue) => {},
- Ok(_) => return Ok(()),
- Err(_) => unreachable!(),
+ Ok(S::Skipped) | Ok(S::Continue) => {},
+ Ok(S::Break) => return Ok(()),
+ Err(err) => return Err(StructWalkError::Tag(err)),
}
// Give the field names before hand.
- match $crate::macros::visit_tag::<{ $crate::TAG_FIELD_NAMES.to_int() }, E, _>(
+ match $crate::protocol::visitor::tag::visit_tag::<{ $crate::TAG_FIELD_NAMES.to_int() }, E, _>(
visitor,
$crate::walkers::core::tag::StaticSliceWalker::<_, $crate::walkers::core::value::ValueWalker<&str>>::new(&[$(
stringify!($field)
),*])
).await {
- Ok($crate::Flow::Continue) => {},
- Ok(_) => return Ok(()),
- // Err(err) => return Err(StructWalkError::Tag(err)),
- Err(err) => todo!(),
+ Ok(S::Skipped) | Ok(S::Continue) => {},
+ Ok(S::Break) => return Ok(()),
+ Err(err) => return Err(StructWalkError::FieldTag(err)),
}
if !matches!($crate::protocol::visitor::sequence::visit_sequence::<E>(
@@ -219,26 +234,30 @@ macro_rules! Walk {
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 {
+ use $crate::protocol::visitor::Status as S;
+
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, _>(
+ match $crate::protocol::visitor::tag::visit_tag::<{ $crate::TAG_FIELD.to_int() }, E, _>(
visitor,
$crate::walkers::core::noop::NoopWalker::new()
).await {
- Ok($crate::Flow::Continue) => {},
- _ => return Flow::Done,
+ Ok(S::Skipped) | Ok(S::Continue) => {},
+ Ok(S::Break) => return Flow::Break,
+ Err(err) => return Flow::Break,
}
- match $crate::macros::visit_tag::<{ $crate::TAG_KEY.to_int() }, E, _>(
+ match $crate::protocol::visitor::tag::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!(),
+ Ok(S::Skipped) | Ok(S::Continue) => {},
+ Ok(S::Break) => return Flow::Break,
+ Err(err) => return Flow::Break,
}
+ // Use the type's walker in the same mode as the parent struct.
let walker = $crate::Walk::<M, E>::into_walker(&self.value.$field);
$crate::Walker::<E>::walk(walker, visitor).await;
self.field += 1;