Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs170
1 files changed, 123 insertions, 47 deletions
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!();
}