Diffstat (limited to 'src/walk/walkers/core/struct.rs')
-rw-r--r--src/walk/walkers/core/struct.rs647
1 files changed, 647 insertions, 0 deletions
diff --git a/src/walk/walkers/core/struct.rs b/src/walk/walkers/core/struct.rs
new file mode 100644
index 0000000..a07557f
--- /dev/null
+++ b/src/walk/walkers/core/struct.rs
@@ -0,0 +1,647 @@
+use core::{any::TypeId, marker::PhantomData};
+
+use crate::{
+ any::static_wrapper::BorrowedStatic,
+ any_trait,
+ effect::{Effect, Future},
+ never::Never,
+ protocol::{
+ visitor::{
+ recoverable::{visit_recoverable, DynRecoverable, RecoverableScope},
+ request_hint::visit_request_hint,
+ sequence::{visit_sequence, DynSequence, SequenceKnown, SequenceScope},
+ tag::{visit_tag, DynTag, TagConst, TagDyn, TagError, TagHint, TagKnown},
+ value::{visit_value, DynValue},
+ Status,
+ },
+ walker::hint::{DynHint, HintMeta},
+ walker::hint::{Hint, Known},
+ Visitor,
+ },
+ Flow, WalkerTypes, TAG_FIELD_NAMES, TAG_MAP, TAG_STRUCT, TAG_TYPE_ID, TAG_TYPE_NAME,
+};
+
+use super::{noop::NoopWalker, tag::StaticSliceWalker, value::ValueWalker};
+
+/// Walker for a borrow of a struct.
+///
+/// This walker implements the struct flow. The struct cannot contain lifetimes.
+pub struct StructWalker<'ctx, T, I: StructTypeInfo<'ctx, M>, M, E> {
+ /// Struct value to walk.
+ value: &'ctx T,
+
+ /// Index of the current field to walk.
+ index: usize,
+
+ /// Error if there was one.
+ ///
+ /// The visitor tracks it's own errors.
+ error: Option<StructWalkErrorKind<I::FieldError>>,
+
+ _marker: PhantomData<fn() -> (I, M, E)>,
+}
+
+/// Type info about a struct needed by [`StructWalker`].
+pub trait StructTypeInfo<'ctx, M>: 'static {
+ /// Name of the struct.
+ const NAME: &'static str;
+
+ /// The field names in definition order.
+ const FIELDS: &'static [&'static str];
+
+ /// The walking errors for the fields.
+ type FieldError: Send;
+
+ /// The struct being described.
+ type T: Send;
+
+ /// Walk the given field.
+ fn walk_field<'a, E: Effect<'ctx>>(
+ index: usize,
+ value: &'ctx Self::T,
+ visitor: Visitor<'a, 'ctx>,
+ ) -> Future<'a, 'ctx, Result<Flow, Self::FieldError>, E>;
+}
+
+#[derive(Debug)]
+enum StructWalkErrorKind<T> {
+ /// Error with visiting a tag for the struct.
+ ///
+ /// This error shouldn't really happen if the visitor behaves.
+ Tag(TagError<Never>),
+
+ /// Error with visiting a tag for a struct's field.
+ ///
+ /// This error shouldn't really happen if the visitor behaves.
+ FieldTag(TagError<TagError<Never>>),
+
+ /// Error with visiting a field.
+ Field(T),
+}
+
+/// Error from walking a struct.
+#[derive(Debug)]
+pub struct StructWalkError<T> {
+ kind: StructWalkErrorKind<T>,
+}
+
+impl<'ctx, T, I, M, E> StructWalker<'ctx, T, I, M, E>
+where
+ I: StructTypeInfo<'ctx, M>,
+{
+ /// Create walker from a borrow of a struct.
+ pub fn new(value: &'ctx T) -> Self {
+ Self {
+ value,
+ index: 0,
+ error: None,
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl<'ctx, T, I, M, E> WalkerTypes for StructWalker<'ctx, T, I, M, E>
+where
+ I: StructTypeInfo<'ctx, M>,
+{
+ type Error = StructWalkError<I::FieldError>;
+ type Output = ();
+}
+
+impl<'ctx, T, I, E, M> crate::Walker<'ctx, E> for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M, T = T>,
+ T: Sync + 'static,
+{
+ fn walk<'a>(
+ mut self,
+ visitor: Visitor<'a, 'ctx>,
+ ) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
+ where
+ Self: 'a,
+ {
+ E::wrap(async {
+ // Use the recoverable walk to not duplicate the code.
+ let _ = RecoverableScope::<'ctx, E>::new_walk(&mut self, visitor).await;
+
+ // Get the error if there was one.
+ match self.error {
+ Some(err) => Err(StructWalkError { kind: err }),
+ None => Ok(()),
+ }
+ })
+ }
+}
+
+any_trait! {
+ impl['a, 'ctx, T, I, M, E] StructWalker<'ctx, T, I, M, E> = [
+ DynHint<'a, 'ctx, DynRecoverable<'a, 'ctx, E>, E>,
+ DynHint<'a, 'ctx, DynSequence<'a, 'ctx, E>, E>,
+ DynHint<'a, 'ctx, DynValue<'a, 'ctx, BorrowedStatic<'ctx, T>, E>, E>,
+ DynHint<'a, 'ctx, DynTag<'a, 'ctx, TagDyn, E>, E>,
+ DynHint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E>, E>,
+ DynHint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E>, E>,
+ DynHint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_MAP.to_int() }>, E>, E>,
+ DynHint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>, E>,
+ DynHint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>, E>,
+ ] where
+ E: Effect<'ctx>,
+ T: Sync + 'static,
+ I: StructTypeInfo<'ctx, M, T = T>
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E> Hint<'a, 'ctx, DynRecoverable<'a, 'ctx, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M, T = T>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynRecoverable<'a, 'ctx, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_recoverable::<E>(visitor, self),
+ |status| match status {
+ Status::Skipped(_) => Flow::Continue,
+ Status::Flow(flow) => flow,
+ },
+ )
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynRecoverable<'a, 'ctx, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynRecoverable<'a, 'ctx, E>>, ()>, E> {
+ E::ready(Ok(()))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E>
+ Hint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynTag<'a, 'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>(
+ TagConst,
+ visitor,
+ StaticSliceWalker::<_, ValueWalker<&'static str>>::new(I::FIELDS),
+ ),
+ |status| match status {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::FieldTag(err));
+ Flow::Break
+ }
+ Ok(Status::Skipped(_)) => Flow::Continue,
+ Ok(Status::Flow(flow)) => flow,
+ },
+ )
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynTag<'a, 'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E> as HintMeta<
+ 'ctx,
+ >>::Hint,
+ ) -> Future<
+ 'a,
+ 'ctx,
+ Result<Known<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>>, ()>,
+ E,
+ > {
+ E::ready(Ok(TagKnown {
+ kind_available: Some(true),
+ }))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E>
+ Hint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>(TagConst, visitor, ValueWalker::new(I::NAME)),
+ |status| match status {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ Flow::Break
+ }
+ Ok(Status::Skipped(_)) => Flow::Continue,
+ Ok(Status::Flow(flow)) => flow,
+ },
+ )
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<
+ 'a,
+ 'ctx,
+ Result<Known<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>>, ()>,
+ E,
+ > {
+ E::ready(Ok(TagKnown {
+ kind_available: Some(true),
+ }))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E>
+ Hint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_MAP.to_int() }>, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynTag<'a, 'ctx, TagConst<{ TAG_MAP.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()),
+ |status| match status {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ Flow::Break
+ }
+ Ok(Status::Skipped(_)) => Flow::Continue,
+ Ok(Status::Flow(flow)) => flow,
+ },
+ )
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynTag<'a, 'ctx, TagConst<{ TAG_MAP.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<
+ 'a,
+ 'ctx,
+ Result<Known<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_MAP.to_int() }>, E>>, ()>,
+ E,
+ > {
+ E::ready(Ok(TagKnown {
+ kind_available: Some(true),
+ }))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E>
+ Hint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynTag<'a, 'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()),
+ |status| match status {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ Flow::Break
+ }
+ Ok(Status::Skipped(_)) => Flow::Continue,
+ Ok(Status::Flow(flow)) => flow,
+ },
+ )
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynTag<'a, 'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<
+ 'a,
+ 'ctx,
+ Result<Known<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E>>, ()>,
+ E,
+ > {
+ E::ready(Ok(TagKnown {
+ kind_available: Some(true),
+ }))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E>
+ Hint<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>(
+ TagConst,
+ visitor,
+ ValueWalker::new(TypeId::of::<T>()),
+ ),
+ |status| match status {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ Flow::Break
+ }
+ Ok(Status::Skipped(_)) => Flow::Continue,
+ Ok(Status::Flow(flow)) => flow,
+ },
+ )
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<
+ 'a,
+ 'ctx,
+ Result<Known<'a, 'ctx, DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E>>, ()>,
+ E,
+ > {
+ E::ready(Ok(TagKnown {
+ kind_available: Some(true),
+ }))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E> Hint<'a, 'ctx, DynTag<'a, 'ctx, TagDyn, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ hint: <DynTag<'a, 'ctx, TagDyn, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ match hint.kind.0 {
+ crate::TAG_TYPE_ID => Hint::<
+ 'a,
+ 'ctx,
+ DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_ID.to_int() }>, E>,
+ E,
+ >::hint(self, visitor, TagHint { kind: TagConst }),
+ crate::TAG_STRUCT => Hint::<
+ 'a,
+ 'ctx,
+ DynTag<'a, 'ctx, TagConst<{ TAG_STRUCT.to_int() }>, E>,
+ E,
+ >::hint(self, visitor, TagHint { kind: TagConst }),
+ crate::TAG_MAP => Hint::<
+ 'a,
+ 'ctx,
+ DynTag<'a, 'ctx, TagConst<{ TAG_MAP.to_int() }>, E>,
+ E,
+ >::hint(self, visitor, TagHint { kind: TagConst }),
+ crate::TAG_TYPE_NAME => Hint::<
+ 'a,
+ 'ctx,
+ DynTag<'a, 'ctx, TagConst<{ TAG_TYPE_NAME.to_int() }>, E>,
+ E,
+ >::hint(self, visitor, TagHint { kind: TagConst }),
+ crate::TAG_FIELD_NAMES => Hint::<
+ 'a,
+ 'ctx,
+ DynTag<'a, 'ctx, TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>,
+ E,
+ >::hint(self, visitor, TagHint { kind: TagConst }),
+ _ => E::ready(Flow::Continue),
+ }
+ }
+
+ fn known(
+ &'a mut self,
+ hint: &'a <DynTag<'a, 'ctx, TagDyn, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynTag<'a, 'ctx, TagDyn, E>>, ()>, E> {
+ E::ready(match hint.kind {
+ TagDyn(crate::TAG_TYPE_ID) | TagDyn(crate::TAG_STRUCT) => Ok(TagKnown {
+ kind_available: Some(true),
+ }),
+ _ => Ok(TagKnown {
+ kind_available: Some(false),
+ }),
+ })
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E> Hint<'a, 'ctx, DynValue<'a, 'ctx, BorrowedStatic<'ctx, T>, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M>,
+ T: Sync + 'static,
+{
+ fn hint(&'a mut self, visitor: Visitor<'a, 'ctx>, _hint: ()) -> Future<'a, 'ctx, Flow, E> {
+ E::map(
+ visit_value::<_, E>(visitor, BorrowedStatic(self.value)),
+ |status| match status {
+ Status::Skipped(_) => Flow::Continue,
+ Status::Flow(flow) => flow,
+ },
+ )
+ }
+
+ fn known(&'a mut self, _hint: &'a ()) -> Future<'a, 'ctx, Result<(), ()>, E> {
+ E::ready(Ok(()))
+ }
+}
+
+impl<'a, 'ctx: 'a, T, I, M, E> Hint<'a, 'ctx, DynSequence<'a, 'ctx, E>, E>
+ for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M, T = T>,
+ T: Sync,
+{
+ fn hint(
+ &'a mut self,
+ visitor: Visitor<'a, 'ctx>,
+ _hint: <DynSequence<'a, 'ctx, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Flow, E> {
+ E::map(visit_sequence::<E>(visitor, self), |status| match status {
+ Status::Skipped(_) => Flow::Continue,
+ Status::Flow(flow) => flow,
+ })
+ }
+
+ fn known(
+ &'a mut self,
+ _hint: &'a <DynSequence<'a, 'ctx, E> as HintMeta<'ctx>>::Hint,
+ ) -> Future<'a, 'ctx, Result<Known<'a, 'ctx, DynSequence<'a, 'ctx, E>>, ()>, E> {
+ let len = I::FIELDS.len();
+
+ E::ready(Ok(SequenceKnown {
+ len: (len, Some(len)),
+ }))
+ }
+}
+
+impl<'ctx, T, I, M, E> SequenceScope<'ctx, E> for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M, T = T>,
+{
+ fn size_hint<'a>(&'a mut self) -> Future<'a, 'ctx, (usize, Option<usize>), E> {
+ let len = I::FIELDS.len();
+
+ E::ready((len, Some(len)))
+ }
+
+ fn next<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> {
+ if self.index >= I::FIELDS.len() {
+ return E::ready(Flow::Done);
+ }
+
+ let index = self.index;
+ self.index += 1;
+
+ E::map(
+ I::walk_field::<E>(index, self.value, visitor),
+ |result| match result {
+ Ok(flow) => flow,
+ Err(err) => {
+ // Record the error and signal a break.
+ self.error = Some(StructWalkErrorKind::Field(err));
+ Flow::Break
+ }
+ },
+ )
+ }
+}
+
+impl<'ctx, T, I, M, E> RecoverableScope<'ctx, E> for StructWalker<'ctx, T, I, M, E>
+where
+ E: Effect<'ctx>,
+ I: StructTypeInfo<'ctx, M, T = T>,
+ T: Sync + 'static,
+{
+ fn new_walk<'a>(&'a mut self, visitor: Visitor<'a, 'ctx>) -> Future<'a, 'ctx, Flow, E> {
+ // Reset the errors to default state.
+ self.error = None;
+
+ // Reset the field index to the default.
+ self.index = 0;
+
+ E::wrap(async move {
+ // We should check if the visitor wants something specific.
+ match visit_request_hint::<E>(visitor, self).await {
+ Flow::Continue => {}
+ flow => return flow,
+ }
+
+ // Attempt to visit the value directly.
+ match visit_value::<_, E>(visitor, BorrowedStatic(self.value)).await {
+ Status::Skipped(_) | Status::Flow(Flow::Continue) => {}
+ Status::Flow(flow) => return flow,
+ }
+
+ // Follow the standard set of protocols for a struct.
+ // - Tagged: type ID
+ // - Tagged: struct
+ // - Tagged: struct name
+ // - Tagged: struct field names
+ // - Sequence: the fields
+
+ match visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>(
+ TagConst,
+ visitor,
+ ValueWalker::new(TypeId::of::<T>()),
+ )
+ .await
+ {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ return Flow::Break;
+ }
+ Ok(Status::Skipped(_)) | Ok(Status::Flow(Flow::Continue)) => {}
+ Ok(Status::Flow(flow)) => return flow,
+ }
+
+ match visit_tag::<TagConst<{ TAG_STRUCT.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()).await {
+ Ok(Status::Skipped(_)) => {
+ match visit_tag::<TagConst<{ TAG_MAP.to_int() }>, E, _>(TagConst, visitor, NoopWalker::new()).await
+ {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ return Flow::Break;
+ }
+ Ok(Status::Skipped(_)) | Ok(Status::Flow(Flow::Continue)) => {}
+ Ok(Status::Flow(flow)) => return flow,
+ }
+ }
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ return Flow::Break;
+ }
+ Ok(Status::Flow(Flow::Continue)) => {}
+ Ok(Status::Flow(flow)) => return flow,
+ }
+
+ match visit_tag::<TagConst<{ TAG_TYPE_NAME.to_int() }>, E, _>(TagConst, visitor, ValueWalker::new(I::NAME))
+ .await
+ {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::Tag(err));
+ return Flow::Break;
+ }
+ Ok(Status::Skipped(_)) | Ok(Status::Flow(Flow::Continue)) => {}
+ Ok(Status::Flow(flow)) => return flow,
+ }
+
+ match visit_tag::<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E, _>(
+ TagConst,
+ visitor,
+ StaticSliceWalker::<_, ValueWalker<&'static str>>::new(I::FIELDS),
+ )
+ .await
+ {
+ Err(err) => {
+ self.error = Some(StructWalkErrorKind::FieldTag(err));
+ return Flow::Break;
+ }
+ Ok(Status::Skipped(_)) | Ok(Status::Flow(Flow::Continue)) => {}
+ Ok(Status::Flow(flow)) => return flow,
+ }
+
+ match visit_sequence::<E>(visitor, self).await {
+ Status::Flow(Flow::Continue) | Status::Skipped(_) => {}
+ Status::Flow(flow) => return flow,
+ }
+
+ Flow::Continue
+ })
+ }
+}