Diffstat (limited to 'tests/builder_enum.rs')
-rw-r--r--tests/builder_enum.rs179
1 files changed, 40 insertions, 139 deletions
diff --git a/tests/builder_enum.rs b/tests/builder_enum.rs
index dbdc60f..b589d6c 100644
--- a/tests/builder_enum.rs
+++ b/tests/builder_enum.rs
@@ -1,167 +1,67 @@
use treaty::{
any::{OwnedStatic, TypeName},
- builders::core::r#enum::{EnumBuildInfo, EnumBuilder},
effect::{
- blocking::Blocking, Effect, EffectExt as _, Effective as _, EffectiveExt as _,
- ErasedEffective,
+ blocking::Blocking, Effect, Effective as _, EffectiveExt as _, ErasedEffective,
+ ResultErrorExt as _,
},
protocol::{
- visitor::{tags, visit_recoverable, visit_tag, visit_value, DynRecoverableScope, TagConst},
- DynVisitor,
+ visitor::{tags, DynRecoverableScope},
+ AsVisitor as _, DynVisitor,
},
- walkers::core::value::ValueWalker,
- Build, BuildExt as _, Builder, Flow, Status, WalkExt as _,
+ walkers::core::value::{BorrowWalker, ValueWalker},
+ Build, BuildExt as _, Builder, BuilderTypes, Status,
};
use crate::common::protocol::{
- recoverable::MockRecoverableScopeVisitor, value::ValueVisitorExt as _,
+ recoverable::{MockRecoverableScopeVisitor, RecoverableVisitorExt as _},
+ tag::TagVisitorExt as _,
+ value::ValueVisitorExt as _,
};
+use macro_rules_attribute::derive;
+
mod common;
-#[derive(PartialEq, Debug)]
+#[derive(Build!, PartialEq, Debug)]
enum X {
A(f32),
B(bool),
}
-impl<'ctx, M, E: Effect> Build<'ctx, M, E> for X {
- type Builder = EnumBuilder<'ctx, Info, M, E>;
-}
-
-enum Info {}
-
-enum XBuilders<'ctx, M, E: Effect> {
- A(<f32 as Build<'ctx, M, E>>::Builder),
- B(<bool as Build<'ctx, M, E>>::Builder),
-}
-
-#[derive(Copy, Clone, Debug)]
-enum XMarker {
- A,
- B,
-}
-
-impl core::fmt::Display for XMarker {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- todo!()
- }
-}
-
-impl<'ctx, M, E: Effect> EnumBuildInfo<'ctx, M, E> for Info {
- type Builders = XBuilders<'ctx, M, E>;
-
- type Seed = ();
-
- type Error = i32;
-
- type ValueT = OwnedStatic<X>;
-
- type T = X;
-
- type VariantMarker = XMarker;
-
- fn new_builder<'a>(
- _seed: Self::Seed,
- variant: Self::VariantMarker,
- ) -> ErasedEffective<'a, Self::Builders, E> {
- match variant {
- XMarker::A => {
- Builder::<E>::from_seed(Default::default()).map(|builder| XBuilders::A(builder))
- }
- XMarker::B => {
- Builder::<E>::from_seed(Default::default()).map(|builder| XBuilders::B(builder))
- }
- }
- }
-
- fn from_value<'a>(value: TypeName::T<'a, 'ctx, Self::ValueT>) -> Self::T {
- value.0
- }
-
- fn as_visitor<'a>(builder: &'a mut Self::Builders) -> DynVisitor<'a, 'ctx> {
- match builder {
- XBuilders::A(builder) => builder.as_visitor(),
- XBuilders::B(builder) => builder.as_visitor(),
- }
- }
-
- fn marker_from_name(name: &str) -> Option<Self::VariantMarker> {
- match name {
- "A" => Some(XMarker::A),
- "B" => Some(XMarker::B),
- _ => None,
- }
- }
+#[test]
+fn enum_builder_takes_unsigned_integer_variant_tag() {
+ let mut builder = X::new_builder();
- fn marker_from_discriminant(discriminant: u32) -> Option<Self::VariantMarker> {
- match discriminant {
- 0 => Some(XMarker::A),
- 1 => Some(XMarker::B),
- _ => None,
- }
- }
+ // Use the int variant then value flow.
+ {
+ // Signal the first variant.
+ builder.visit_tag_and_done::<{ tags::Variant::VALUE }, _>(ValueWalker::new(0u32));
- fn finish_builder<'a>(
- builder: Self::Builders,
- ) -> ErasedEffective<'a, Result<Self::T, Self::Error>, E> {
- match builder {
- XBuilders::A(builder) => builder.build().map(|value| Ok(X::A(value.unwrap()))),
- XBuilders::B(builder) => builder.build().map(|value| Ok(X::B(value.unwrap()))),
- }
+ // Give the value for the variant.
+ builder.visit_value_and_done(OwnedStatic(1.23f32));
}
- fn guess_variant<'a>(
- _seed: Self::Seed,
- scope: DynRecoverableScope<'a, 'ctx, E>,
- ) -> ErasedEffective<'a, Result<Self::T, Self::Error>, E> {
- E::as_ctx(scope, |scope| {
- <<f32 as Build<M, E>>::Builder as Builder<_>>::from_seed(Default::default())
- .map(|builder| (scope, builder))
- .as_ctx(|(scope, builder)| scope.new_walk(builder.as_visitor()).cast())
- .then(|((_, builder), result)| builder.build())
- .map(|result| result.map(X::A))
- .cast()
- })
- .as_ctx(|(scope, result)| {
- <<bool as Build<M, E>>::Builder as Builder<_>>::from_seed(Default::default())
- .map(|builder| (scope, builder))
- .as_ctx(|(scope, builder)| scope.new_walk(builder.as_visitor()).cast())
- .then(|((_, builder), result)| builder.build())
- .map(|result| result.map(X::B))
- .cast()
- })
- .map(|((scope, _), result)| match result {
- Ok(value) => Ok(value),
- Err(err) => todo!("{}", err),
- })
- }
+ assert_eq!(builder.build().value().unwrap(), X::A(1.23));
}
#[test]
-fn demo() {
+fn enum_builder_takes_string_variant_tag() {
let mut builder = X::new_builder();
- assert_eq!(
- visit_tag::<tags::Variant, Blocking, _>(
- TagConst,
- builder.as_visitor(),
- ValueWalker::new(0u32),
- )
- .value()
- .unwrap(),
- Flow::Done.into()
- );
-
- builder
- .as_visitor()
- .visit_value_and_done(OwnedStatic(1.23f32));
+ // Use the string variant then value flow.
+ {
+ // Signal the A variant.
+ builder.visit_tag_and_done::<{ tags::Variant::VALUE }, _>(BorrowWalker::new("A"));
+
+ // Give the value for the variant.
+ builder.visit_value_and_done(OwnedStatic(1.23f32));
+ }
assert_eq!(builder.build().value().unwrap(), X::A(1.23));
}
#[test]
-fn demo2() {
+fn enum_builder_can_guess_the_variant() {
let mut builder = X::new_builder();
// Use the recoverable flow.
@@ -169,11 +69,15 @@ fn demo2() {
let mut scope = MockRecoverableScopeVisitor::<Blocking>::new();
// The first builder for a f32 won't work.
- // In a real walker the scope would always walk the same.
- scope.expect_new_walk().once().return_const(Status::Ok);
+ scope.expect_new_walk().once().returning(|mut visitor| {
+ // The value for the B variant.
+ visitor.visit_value_and_skipped(OwnedStatic(true));
+
+ Status::Ok
+ });
// The second builder will work.
- scope.expect_new_walk().once().returning(|visitor| {
+ scope.expect_new_walk().once().returning(|mut visitor| {
// The value for the B variant.
visitor.visit_value_and_done(OwnedStatic(true));
@@ -182,10 +86,7 @@ fn demo2() {
// Visit a recoverable scope the enum builder can use to try and find
// a variant that can be built.
- assert_eq!(
- visit_recoverable(builder.as_visitor(), &mut scope).value(),
- Flow::Done.into()
- );
+ builder.visit_recoverable_and_done(&mut scope);
}
// The enum should have a value now.