Diffstat (limited to 'src/build/builders/core/struct.rs')
-rw-r--r--src/build/builders/core/struct.rs168
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))
}
}