use core::any::TypeId;
use effectful::{
bound::Dynamic,
effective::{Effective, Canonical},
environment::{Environment},
higher_ranked::{for_lt, Rank1, WithLt},
SendSync,
DynBind,
};
use crate::{
any::{type_name, AnyTrait, BorrowedStatic, OwnedStatic},
hkt::Marker,
protocol::{
visitor::{
request_hint, tags, visit_sequence, visit_tag, visit_value, EffectiveVisitExt as _,
Recoverable, RecoverableScope, Sequence, SequenceHint, SequenceKnown, SequenceScope,
Tag, TagConst, TagDyn, TagError, TagHint, TagKnown, Value, ValueKnown, VisitResult,
},
walker::hint::{DynVisitorWith, Hint, HintMeta},
DynVisitor, DynWalker,
},
walk::DynWalkerAdapter,
Flow, Never, Status,
};
use super::{noop::NoopWalker, value::ValueWalker};
/// Walker for a borrow of a struct.
///
/// This walker implements the struct flow. The struct cannot contain lifetimes.
#[derive(SendSync)]
pub struct StructWalker<'ctx, I: StructTypeInfo<'ctx, M, E, S = S>, S, M, E: Environment> {
/// Struct value to walk.
value: Dynamic<&'ctx I::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>>,
_generics: Marker<E>,
}
/// Type info about a struct needed by [`StructWalker`].
pub trait StructTypeInfo<'ctx, M, E: Environment>: '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: DynBind<E> + core::fmt::Debug;
type S: 'static;
/// The struct being described.
type T: DynBind<E>;
/// Walk the given field.
fn walk_field<'a, 'lt>(
index: usize,
value: &'ctx Self::T,
visitor: DynVisitor<'a, 'lt, 'ctx, E>,
) -> Canonical<'a, Result<Flow, Self::FieldError>, E>;
}
#[derive(Debug, PartialEq, Clone, Copy, SendSync)]
#[allow(unused)]
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, PartialEq, Copy, Clone, SendSync)]
#[allow(unused)]
pub struct StructWalkError<T> {
kind: StructWalkErrorKind<T>,
}
impl<'ctx, I, S, M, E: Environment> StructWalker<'ctx, I, S, M, E>
where
I: StructTypeInfo<'ctx, M, E, S = S>,
{
/// Create walker from a borrow of a struct.
pub fn new(value: &'ctx I::T) -> Self {
Self {
value: Dynamic(value),
index: 0,
error: None,
_generics: Default::default(),
}
}
fn record_tag_error<U>(
&mut self,
result: Result<VisitResult<U>, TagError<Never>>,
) -> VisitResult<U> {
result.unwrap_or_else(|err| {
self.error = Some(StructWalkErrorKind::Tag(err));
Flow::Err.into()
})
}
}
impl<'lt, 'ctx, I, S, E, M> crate::Walker<'ctx, E> for StructWalker<'ctx, I, S, M, E>
where
E: Environment,
I: StructTypeInfo<'ctx, M, E, S = S>,
Self: AnyTrait<'lt, 'ctx> + RecoverableScope<'ctx, E>,
{
type Error = StructWalkError<I::FieldError>;
type Output = ();
#[inline(always)]
fn walk<'b: 'c, 'd: 'c, 'c>(
self,
visitor: DynVisitor<'b, 'd, 'ctx, E>,
) -> Canonical<'c, Result<Self::Output, Self::Error>, E>
where
Self: 'c,
{
E::value((self, visitor))
.update_map((), |_, (this, visitor)| {
RecoverableScope::<'ctx, E>::new_walk::<'_, '_, '_, '_>(this, visitor.cast()).cast()
})
.map((), |_, ((this, _), _)| match this.error {
Some(err) => Err(StructWalkError { kind: err }),
None => Ok(()),
})
.cast()
// E::ready(self).as_ctx_for::<'ctx, '_>(|this, _| {
// (RecoverableScope::<'ctx, E>::new_walk::<'_, 'b, '_>(this, visitor), PhantomData)
// });
// E::wrap(async move {
// // Use the recoverable walk to not duplicate the code.
// let _ = RecoverableScope::<'ctx, E>::new_walk(&mut self, visitor.cast()).await;
//
// // Get the error if there was one.
// match self.error {
// Some(err) => Err(StructWalkError { kind: err }),
// None => Ok(()),
// }
// })
}
}
pub enum StaticType {}
impl<'lt, 'ctx: 'lt, I, M: 'lt, E> AnyTrait<'lt, 'ctx> for StructWalker<'ctx, I, StaticType, M, E>
where
E: Environment,
I: StructTypeInfo<'ctx, M, E, S = StaticType>,
M: 'ctx,
I::T: 'static,
Dynamic<&'ctx I::T>: DynBind<E>,
Dynamic<BorrowedStatic<'ctx, I::T>>: DynBind<E>,
for<'a, 'b> Dynamic<&'a BorrowedStatic<'b, I::T>>: DynBind<E>,
Dynamic<TypeId>: DynBind<E>,
Dynamic<OwnedStatic<TypeId>>: DynBind<E>,
{
}
// any_trait! {
// impl['ctx, I, M][E] StructWalker<'ctx, I, StaticType, M, E> = [
// HintProto<RecoverableProto<E>>,
// HintProto<SequenceProto<E>>,
// HintProto<ValueProto<BorrowedStaticHrt<I::T>, E>>,
// HintProto<TagProto<TagDyn, E>>,
// HintProto<TagProto<tags::TypeId, E>>,
// HintProto<TagProto<tags::Struct, E>>,
// HintProto<TagProto<tags::Map, E>>,
// HintProto<TagProto<tags::TypeName, E>>,
// HintProto<TagProto<tags::FieldNames, E>>,
// ] where
// }
impl<'lt2, 'ctx, I, S, M, E> Hint<'ctx, type_name::Raised<'static, 'ctx, dyn Recoverable<'ctx, E>>>
for StructWalker<'ctx, I, S, M, E>
where
E: Environment,
I: StructTypeInfo<'ctx, M, E, S = S>,
Self: AnyTrait<'lt2, 'ctx> + RecoverableScope<'ctx, E>,
{
#[inline(always)]
fn hint<'this, 'visitor, 'lt: 'e, 'hint, 'e>(
&'this mut self,
_visitor: DynVisitorWith<
'visitor,
'lt,
'ctx,
type_name::Raised<'static, 'ctx, dyn Recoverable<'ctx, E>>,
>,
_hint: (),
) -> Canonical<'e, VisitResult, E>
where
'ctx: 'this + 'visitor + 'hint + 'e,
{
todo!()
// E::map(
// visit_recoverable::<E>(visitor, self),
// |status| match status {
// VisitResult::Skipped(_) => Flow::Continue,
// VisitResult::Control(flow) => flow,
// },
// )
}
fn known<'a>(
&'a mut self,
hint: &'a WithLt<'a, Rank1<()>>,
) -> Canonical<'a, Result<WithLt<'a, Rank1<()>>, ()>, E>
where
WithLt<'a, Rank1<()>>: DynBind<E>,
{
E::value(Ok(())).cast()
}
}
// impl<'c, 'ctx: 'c, I, S, M, E> Hint<'ctx, dyn Tag<'ctx, tags::FieldNames, E> + 'c>
// for StructWalker<'ctx, I, S, M, E>
// where
// Self: DynBind<E>,
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = S>,
// {
// #[inline(always)]
// fn hint<'this, 'visitor, 'hint, 'e>(
// &'this mut self,
// _visitor: DynVisitorWith<
// 'visitor,
// 'ctx,
// dyn Tag<'ctx, tags::FieldNames, E> + 'c,
// >,
// _hint: TagHint<tags::FieldNames>,
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// todo!()
// // 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::Err
// // }
// // Ok(VisitResult::Skipped(_)) => Flow::Continue,
// // Ok(VisitResult::Control(flow)) => flow,
// // },
// // )
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<()>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<TagKnown>>: DynBind<Protocol::Env>
// {
// E::value(Ok(TagKnown {
// kind_available: Some(true),
// }))
// .cast()
// }
// }
//
// impl<'c, 'ctx: 'c, I, S, M, E> Hint<'ctx, dyn Tag<'ctx, tags::TypeName, E> + 'c>
// for StructWalker<'ctx, I, S, M, E>
// where
// Self: DynBind<E>,
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = S>,
// {
// #[inline(always)]
// fn hint<'this, 'visitor, 'hint, 'e>(
// &'this mut self,
// _visitor: DynVisitorWith<'visitor, 'ctx, dyn Tag<'ctx, tags::TypeName, E> + 'c>,
// _hint: TagHint<tags::TypeName>,
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// todo!()
// // 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::Err
// // }
// // Ok(VisitResult::Skipped(_)) => Flow::Continue,
// // Ok(VisitResult::Control(flow)) => flow,
// // },
// // )
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<()>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<TagKnown>>: DynBind<Protocol::Env>
// {
// E::value(Ok(TagKnown {
// kind_available: Some(true),
// }))
// .cast()
// }
// }
//
// impl<'c, 'ctx: 'c, I, S, M, E> Hint<'ctx, dyn Tag<'ctx, tags::Map, E> + 'c>
// for StructWalker<'ctx, I, S, M, E>
// where
// Self: DynBind<E>,
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = S>,
// {
// #[inline(always)]
// fn hint<'this, 'visitor, 'hint, 'e>(
// &'this mut self,
// _visitor: DynVisitorWith<'visitor, 'ctx, dyn Tag<'ctx, tags::Map, E> + 'c>,
// _hint: TagHint<tags::Map>,
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// todo!()
// // 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::Err
// // }
// // Ok(VisitResult::Skipped(_)) => Flow::Continue,
// // Ok(VisitResult::Control(flow)) => flow,
// // },
// // )
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<()>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<TagKnown>>: DynBind<Protocol::Env>
// {
// E::value(Ok(TagKnown {
// kind_available: Some(true),
// }))
// .cast()
// }
// }
//
// impl<'c, 'ctx: 'c, I, S, M, E> Hint<'ctx, dyn Tag<'ctx, tags::Struct, E> + 'c>
// for StructWalker<'ctx, I, S, M, E>
// where
// Self: DynBind<E>,
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = S>,
// {
// #[inline(always)]
// fn hint<'this: 'e, 'visitor: 'e, 'hint: 'e, 'e>(
// &'this mut self,
// visitor: DynVisitorWith<'visitor, 'ctx, dyn Tag<'ctx, tags::Struct, E> + 'c>,
// _hint: TagHint<tags::Struct>,
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// E::with(
// (visitor, DynWalkerAdapter::new(NoopWalker::new())),
// |(visitor, noop_walker)| {
// visitor
// .as_known()
// .visit(TagConst, noop_walker)
// .map((), |_, status| {
// VisitResult::Control(status.to_flow().unwrap_or(Flow::Continue))
// })
// .cast()
// },
// )
// .map((), |_, (_, x)| x)
// .cast()
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<()>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<TagKnown>>: DynBind<Protocol::Env>
// {
// E::value(Ok(TagKnown {
// kind_available: Some(true),
// }))
// .cast()
// }
// }
//
// impl<'c, 'ctx: 'c, I, M, E> Hint<'ctx, dyn Tag<'ctx, tags::TypeId, E> + 'c>
// for StructWalker<'ctx, I, StaticType, M, E>
// where
// Self: DynBind<E>,
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = StaticType>,
// I::T: 'static,
// {
// #[inline(always)]
// fn hint<'this, 'visitor, 'hint, 'e>(
// &'this mut self,
// _visitor: DynVisitorWith<'visitor, 'ctx, dyn Tag<'ctx, tags::TypeId, E> + 'c>,
// _hint: TagHint<tags::TypeId>,
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// todo!()
// // E::map(
// // visit_tag::<TagConst<{ TAG_TYPE_ID.to_int() }>, E, _>(
// // TagConst,
// // visitor,
// // ValueWalker::new(TypeId::of::<I::T>()),
// // ),
// // |status| match status {
// // Err(err) => {
// // self.error = Some(StructWalkErrorKind::Tag(err));
// // Flow::Err
// // }
// // Ok(VisitResult::Skipped(_)) => Flow::Continue,
// // Ok(VisitResult::Control(flow)) => flow,
// // },
// // )
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<()>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<TagKnown>>: DynBind<Protocol::Env>
// {
// E::value(Ok(TagKnown {
// kind_available: Some(true),
// }))
// .cast()
// }
// }
//
// impl<'c, 'ctx: 'c, I, M, E> Hint<'ctx, dyn Tag<'ctx, TagDyn, E> + 'c> for StructWalker<'ctx, I, StaticType, M, E>
// where
// Self: DynBind<E>,
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = StaticType>,
// I::T: 'static,
// {
// #[inline(always)]
// fn hint<'this: 'e, 'visitor: 'e, 'hint: 'e, 'e>(
// &'this mut self,
// _visitor: DynVisitorWith<'visitor, 'ctx, dyn Tag<'ctx, TagDyn, E> + 'c>,
// _hint: TagHint<TagDyn>,
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// todo!()
// // match hint.kind.0 {
// // crate::TAG_TYPE_ID => {
// // Hint::<'ctx, TagProto<TagConst<{ TAG_TYPE_ID.to_int() }>, E>>::hint(
// // self,
// // visitor,
// // TagHint { kind: TagConst },
// // )
// // }
// // crate::TAG_STRUCT => {
// // Hint::<'ctx, TagProto<TagConst<{ TAG_STRUCT.to_int() }>, E>>::hint(
// // self,
// // visitor,
// // TagHint { kind: TagConst },
// // )
// // }
// // crate::TAG_MAP => Hint::<'ctx, TagProto<TagConst<{ TAG_MAP.to_int() }>, E>>::hint(
// // self,
// // visitor,
// // TagHint { kind: TagConst },
// // ),
// // crate::TAG_TYPE_NAME => {
// // Hint::<'ctx, TagProto<TagConst<{ TAG_TYPE_NAME.to_int() }>, E>>::hint(
// // self,
// // visitor,
// // TagHint { kind: TagConst },
// // )
// // }
// // crate::TAG_FIELD_NAMES => Hint::<
// // 'ctx,
// // TagProto<TagConst<{ TAG_FIELD_NAMES.to_int() }>, E>,
// // >::hint(self, visitor, TagHint { kind: TagConst }),
// // _ => E::ready(Flow::Continue),
// // }
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<TagHint<TagDyn>>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<TagKnown>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<TagKnown>>: DynBind<Protocol::Env>
// {
// E::value(match hint.kind {
// TagDyn(tags::TypeId::VALUE) | TagDyn(tags::Struct::VALUE) => Ok(TagKnown {
// kind_available: Some(true),
// }),
// _ => Ok(TagKnown {
// kind_available: Some(false),
// }),
// })
// .cast()
// }
// }
//
// impl<'x, 'ctx: 'x, I, M, E> Hint<'ctx, dyn Value<'ctx, BorrowedStatic<'ctx, I::T>, E> + 'x>
// for StructWalker<'ctx, I, StaticType, M, E>
// where
// E: Environment,
// I: StructTypeInfo<'ctx, M, E, S = StaticType>,
// I::T: 'static,
// for<'a, 'b> Dynamic<&'a BorrowedStatic<'b, I::T>>: DynBind<E>,
// Dynamic<&'ctx I::T>: DynBind<E>,
// {
// #[inline(always)]
// fn hint<'this, 'visitor, 'hint, 'e>(
// &'this mut self,
// _visitor: DynVisitorWith<'visitor, 'ctx, dyn Value<'ctx, BorrowedStatic<'ctx, I::T>, E> + 'x>,
// _hint: (),
// ) -> Canonical<'e, VisitResult, E>
// where
// 'ctx: 'this + 'visitor + 'hint + 'e,
// {
// todo!()
// // E::map(
// // visit_value::<_, E>(visitor, BorrowedStatic(self.value)),
// // |status| match status {
// // VisitResult::Skipped(_) => Flow::Continue,
// // VisitResult::Control(flow) => flow,
// // },
// // )
// }
//
// #[inline(always)]
// fn known<'a>(
// &'a mut self,
// hint: &'a WithLt<'a, Rank1<()>>,
// ) -> Canonical<'a, Result<WithLt<'a, Rank1<ValueKnown<'a, BorrowedStatic<'ctx, I::T>>>>, ()>, Protocol::Env>
// where
// WithLt<'a, Rank1<ValueKnown<'a, BorrowedStatic<'ctx, I::T>>>>: DynBind<Protocol::Env>
// {
// E::value(Ok(ValueKnown { preview: None })).cast()
// }
// }
impl<'ctx, I, S, M: 'ctx, E> Hint<'ctx, type_name::Raised<'static, 'ctx, dyn Sequence<'ctx, E>>>
for StructWalker<'ctx, I, S, M, E>
where
Self: DynBind<E>,
E: Environment,
I: StructTypeInfo<'ctx, M, E, S = S>,
{
#[inline(always)]
fn hint<'this: 'e, 'visitor: 'e, 'lt: 'e, 'hint: 'e, 'e>(
&'this mut self,
visitor: DynVisitorWith<
'visitor,
'lt,
'ctx,
type_name::Raised<'static, 'ctx, dyn Sequence<'ctx, E>>,
>,
_hint: SequenceHint,
) -> Canonical<'e, VisitResult, E>
where
'ctx: 'this + 'visitor + 'hint + 'e,
{
E::value((self, visitor))
.update_map((), |_, (this, visitor)| {
visitor
.as_known()
.visit(*this)
.map((), |_, status| {
match status {
VisitResult::Skipped(_) => Flow::Continue,
VisitResult::Control(flow) => flow,
}
.into()
})
.cast()
})
.map((), |_, (_, x)| x)
.cast()
}
#[inline(always)]
fn known<'a>(
&'a mut self,
hint: &'a WithLt<'a, Rank1<SequenceHint>>,
) -> Canonical<'a, Result<WithLt<'a, Rank1<SequenceKnown>>, ()>, E>
where
WithLt<'a, Rank1<SequenceKnown>>: DynBind<E>,
{
let len = I::FIELDS.len();
E::value(Ok(SequenceKnown {
len: (len, Some(len)),
}))
.cast()
}
}
impl<'ctx, I, S, M: 'ctx, E> SequenceScope<'ctx, E> for StructWalker<'ctx, I, S, M, E>
where
Self: DynBind<E>,
E: Environment,
I: StructTypeInfo<'ctx, M, E, S = S>,
{
#[inline(always)]
fn size_hint(&mut self) -> Canonical<'_, (usize, Option<usize>), E> {
let len = I::FIELDS.len();
E::value((len, Some(len))).cast()
}
#[inline(always)]
fn next<'a: 'c, 'd: 'c, 'b: 'c, 'c>(
&'a mut self,
visitor: DynVisitor<'b, 'd, 'ctx, E>,
) -> Canonical<'c, Flow, E> {
if self.index >= I::FIELDS.len() {
return E::value(Flow::Done).cast();
}
let index = self.index;
self.index += 1;
I::walk_field(index, self.value.0, visitor)
.map(self, |this, result| match result {
Ok(flow) => flow,
Err(err) => {
// Record the error and signal a break.
this.error = Some(StructWalkErrorKind::Field(err));
Flow::Err
}
})
.cast()
// 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::Err
// }
// },
// )
}
}
impl<'ctx, I, M: 'ctx, E> RecoverableScope<'ctx, E> for StructWalker<'ctx, I, StaticType, M, E>
where
E: Environment,
I: StructTypeInfo<'ctx, M, E, S = StaticType>,
I::T: 'static,
Dynamic<BorrowedStatic<'ctx, I::T>>: DynBind<E>,
for<'a, 'b> Dynamic<&'a BorrowedStatic<'b, I::T>>: DynBind<E>,
Dynamic<&'ctx I::T>: DynBind<E>,
Dynamic<TypeId>: DynBind<E>,
Dynamic<OwnedStatic<TypeId>>: DynBind<E>,
{
#[inline(always)]
fn new_walk<'a: 'c, 'b: 'c, 'd: 'c, 'c>(
&'a mut self,
visitor: DynVisitor<'b, 'd, 'ctx, E>,
) -> Canonical<'c, Status, E> {
// Reset the errors to default state.
self.error = None;
// Reset the field index to the default.
self.index = 0;
E::value((self, visitor))
.update_map((), |_, (this, visitor)| {
request_hint::<E>(visitor.cast(), DynWalker(*this))
.map((), |_, x| VisitResult::unit_skipped(x))
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, visitor)| {
visit_value::<_, E>(visitor.cast(), BorrowedStatic(this.value.0))
.map((), |_, x| VisitResult::unit_skipped(x))
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, visitor)| {
visit_tag::<tags::TypeId, E, _>(
TagConst,
visitor.cast(),
ValueWalker::new(TypeId::of::<I::T>()),
)
.map(this, |this, result| {
this.record_tag_error(result).unit_skipped()
})
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, visitor)| {
visit_tag::<tags::Struct, E, _>(TagConst, visitor.cast(), NoopWalker::new())
.map(this, |this, result| {
this.record_tag_error(result).unit_skipped()
})
.cast()
})
.cast::<()>()
.if_skipped((), |_, (this, visitor)| {
visit_tag::<tags::Map, E, _>(TagConst, visitor.cast(), NoopWalker::new())
.map(this, |this, result| {
this.record_tag_error(result).unit_skipped()
})
.cast()
})
.cast::<()>()
.if_not_finished((), |_, (this, visitor)| {
visit_sequence::<E>(visitor.cast(), *this)
.map((), |_, x| VisitResult::unit_skipped(x))
.cast()
})
.map((), |_, (_, x)| VisitResult::to_status(x))
.cast()
}
}