Diffstat (limited to 'src/build/builders/core/struct.rs')
| -rw-r--r-- | src/build/builders/core/struct.rs | 168 |
1 files changed, 67 insertions, 101 deletions
diff --git a/src/build/builders/core/struct.rs b/src/build/builders/core/struct.rs index b3983ab..b8ca483 100644 --- a/src/build/builders/core/struct.rs +++ b/src/build/builders/core/struct.rs @@ -1,9 +1,11 @@ -use core::{marker::PhantomData, ops::ControlFlow}; +use core::ops::ControlFlow; use crate::{ any::{OwnedStatic, TempBorrowedStatic, TempBorrowedStaticHrt, TypeName}, any_trait, - effect::{all_ctx, merge_ctx, Effect, Effective, ErasedEffective}, + effect::{ + Effect, EffectExt as _, Effective, EffectiveExt as _, ErasedEffective, ReadyExt as _, + }, hkt::Marker, protocol::{ visitor::{ @@ -12,7 +14,7 @@ use crate::{ }, DynVisitor, }, - Builder, BuilderTypes, DynWalkerObjSafe, Flow, + tri, Builder, BuilderTypes, DynWalkerObjSafe, Flow, }; use super::NoopVisitor; @@ -92,16 +94,14 @@ where where Self: 'a, { - I::new_builders(seed) - .map(|builders| { - Self { - builders, - // Start in tuple mode until a struct or map tag is visited. - mode: StructMode::Tuple, - _generics: Default::default(), - } - }) - .into_erased() + I::new_builders(seed).map(|builders| { + Self { + builders, + // Start in tuple mode until a struct or map tag is visited. + mode: StructMode::Tuple, + _generics: Default::default(), + } + }) } fn build<'a>(self) -> ErasedEffective<'a, Result<Self::Value, Self::Error>, E> @@ -109,11 +109,7 @@ where Self: 'a, { I::from_builders(self.builders) - .map(|builders| match builders { - Ok(value) => Ok(value), - Err(err) => Err(StructError { error: err }), - }) - .into_erased() + .map(|builders| builders.map_err(|err| StructError { error: err })) } fn as_visitor(&mut self) -> DynVisitor<'_, 'ctx> { @@ -144,19 +140,12 @@ where // This signals to go into map mode for the sequence. self.mode = StructMode::Map; - E::ready(NoopVisitor::new()) - .as_ctx( - all_ctx, - |noop, _| { - walker - .walk(DynVisitor(noop)) - .map(|x| x.to_continue().into()) - .into_erased() - }, - merge_ctx, - ) - .map(|(_, value)| value) - .into_erased() + E::ready(NoopVisitor::new()).as_ctx_map(|noop| { + walker + .walk(DynVisitor(noop)) + .map(|x| x.to_continue().into()) + .cast() + }) } } @@ -167,73 +156,55 @@ where E: Effect, { #[inline(always)] - fn visit<'a>( + fn visit<'a: 'c, 'b: 'c, 'c>( &'a mut self, - scope: DynSequenceScope<'a, 'ctx, E>, - ) -> ErasedEffective<'a, VisitResult<DynSequenceScope<'a, 'ctx, E>>, E> { + scope: DynSequenceScope<'b, 'ctx, E>, + ) -> ErasedEffective<'c, VisitResult<DynSequenceScope<'b, 'ctx, E>>, E> + where + 'ctx: 'c, + { match self.mode { StructMode::Tuple => { - E::ready((self, scope, 0)) - .r#loop(|(this, scope, index)| { - if let Some(marker) = I::marker_from_index(*index) { - // Select the visitor for this field. - let visitor = I::as_visitor(marker, &mut this.builders); - - // For rust analyzer. - let scope: &mut DynSequenceScope<'_, '_, E> = scope; - - scope - .next(visitor) - .map(|flow| match flow { - Flow::Continue => { - *index += 1; - - ControlFlow::Continue(()) - } - Flow::Err => { - ControlFlow::Break(VisitResult::Control(Flow::Err)) - } - Flow::Done => { - ControlFlow::Break(VisitResult::Control(Flow::Done)) - } - }) - .into_erased() - } else { - E::ready(ControlFlow::Break(VisitResult::Control(Flow::Done))) - .into_erased() - } - }) - .map(|(_, value)| value) - .into_erased() + // Tuple-like is based on the index of the field. + let mut index = 0; + + // Loop through all the fields getting a value for each one. + E::repeat_map((self, scope), |(this, scope)| { + // Get the marker for the field at this index. + let marker = tri!(I::marker_from_index(index)); + + // Move to the next field for the next iteration. + index += 1; + + // Select the visitor for this field. + let visitor = I::as_visitor(marker, &mut this.builders); + + // Visit the next item in the sequence. + scope.next(visitor).map(Flow::to_control_flow).cast() + }) } - StructMode::Map => E::ready((self, scope)) - .r#loop(|(this, scope)| { - let visitor = FieldVisitor::<I, M, E> { - builders: &mut this.builders, - marker: None, - _marker: Default::default(), - }; - - E::ready((scope, visitor)) - .as_ctx( - all_ctx, - |(scope, visitor), _| { - let scope: &mut DynSequenceScope<'_, '_, _> = scope; - - scope.next(DynVisitor(visitor)).into_erased() - }, - merge_ctx, - ) - .map(|(_, result)| match result { - Flow::Continue => ControlFlow::Continue(()), - Flow::Err => ControlFlow::Break(VisitResult::Control(Flow::Err)), - Flow::Done => ControlFlow::Break(VisitResult::Control(Flow::Done)), - }) - .into_erased() + StructMode::Map => { + // A visitor that knows how to use field names. + let visitor = FieldVisitor::<I, M, E> { + builders: &mut self.builders, + marker: None, + _marker: Default::default(), + }; + + // Loop through all the elements in the sequence. + // Each key value pair will be mapped to a field. + E::repeat_map((visitor, scope), |(visitor, scope)| { + E::as_ctx_map((scope, visitor), |(scope, visitor)| { + // Visit the next element of the sequence. + // When there are no more items in the sequence then the loop ends. + scope.next(DynVisitor(*visitor)).cast() + }) + .map(Flow::to_control_flow) + .cast() }) - .map(|(_, value)| value) - .into_erased(), + } } + .map(Into::into) } } @@ -277,16 +248,11 @@ where }; E::ready((self, visitor, walker)) - .as_ctx( - all_ctx, - |(_, visitor, walker), _| walker.walk(DynVisitor(visitor)).into_erased(), - merge_ctx, - ) + .as_ctx(|(_, visitor, walker)| walker.walk(DynVisitor(visitor)).cast()) .map(|((this, visitor, _), flow)| { this.marker = visitor.field_marker; flow.to_continue().into() }) - .into_erased() } } @@ -321,7 +287,7 @@ where { self.field_marker = I::marker_from_index(index); - E::ready(VisitResult::Control(Flow::Done)).into_erased() + E::ready(VisitResult::Control(Flow::Done)) } } @@ -341,7 +307,7 @@ where { self.field_marker = I::marker_from_name(name); - E::ready(VisitResult::Control(Flow::Done)).into_erased() + E::ready(VisitResult::Control(Flow::Done)) } } @@ -361,6 +327,6 @@ where { self.field_marker = I::marker_from_name(name); - E::ready(VisitResult::Control(Flow::Done)).into_erased() + E::ready(VisitResult::Control(Flow::Done)) } } |