use treaty::{
any::{OwnedStatic, TypeName},
protocol::{
visitor::{tags, DynRecoverableScope},
AsVisitor as _, DynVisitor,
},
walkers::core::value::{BorrowWalker, ValueWalker},
Build, BuildExt as _, Builder, BuilderTypes, Status,
};
use crate::common::{
protocol::{
recoverable::{MockRecoverableScopeVisitor, RecoverableVisitorExt as _},
tag::TagVisitorExt as _,
value::ValueVisitorExt as _,
},
Blocking,
};
use effectful::{
bound::Dynamic,
effective::Effective,
environment::{Environment, NativeForm},
SendSync,
};
use macro_rules_attribute::derive;
mod common;
#[derive(Build!, PartialEq, Debug, SendSync)]
enum X {
A(f32),
B(bool),
}
#[test]
fn enum_builder_takes_unsigned_integer_variant_tag() {
let mut builder = X::new_builder();
// Use the int variant then value flow.
{
// Signal the first variant.
builder.visit_tag_and_done::<{ tags::Variant::VALUE }, _>(ValueWalker::new(0u32));
// Give the value for the variant.
builder.visit_value_and_done(OwnedStatic(1.23f32));
}
assert_eq!(builder.build().into_value().unwrap().0, X::A(1.23));
}
#[test]
fn enum_builder_takes_string_variant_tag() {
let mut builder = X::new_builder();
// 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().into_value().unwrap().0, X::A(1.23));
}
#[test]
fn enum_builder_can_guess_the_variant() {
let mut builder = X::new_builder();
// Use the recoverable flow.
{
let mut scope = MockRecoverableScopeVisitor::<Blocking>::new();
// The first builder for a f32 won't work.
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(|mut visitor| {
// The value for the B variant.
visitor.visit_value_and_done(OwnedStatic(true));
Status::Ok
});
// Visit a recoverable scope the enum builder can use to try and find
// a variant that can be built.
builder.visit_recoverable_and_done(&mut scope);
}
// The enum should have a value now.
assert_eq!(builder.build().into_value().unwrap().0, X::B(true));
}