Diffstat (limited to 'tests/builder_enum.rs')
| -rw-r--r-- | tests/builder_enum.rs | 179 |
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. |