/* use effectful::SendSync; use effectful::blocking::BlockingSpin; use macro_rules_attribute::derive; use treaty::{ any::{OwnedStatic, TempBorrowedStatic}, protocol::{ visitor::{tags, visit_sequence, visit_tag, TagConst, VisitResult}, AsVisitor as _, }, transform::BuildExt as _, walk::walkers::core::noop::NoopWalker, Build, Builder, Flow, }; use crate::common::{ protocol::{sequence::MockSequenceScope, value::ValueVisitorExt as _}, walker::MockWalker, }; mod common; #[derive(Build!, Debug, PartialEq, SendSync)] struct X { a: bool, b: bool, } #[test] fn a_struct_builder_can_build_from_a_sequence_of_field_values() { let mut scope; { // A tuple-like struct is just a sequence. scope = MockSequenceScope::::new(); // First field. scope.expect_next().once().returning(|mut visitor| { // Visit a bool value. visitor.visit_value_and_done(OwnedStatic(true)); // We have another field. Flow::Continue }); // Second field. scope.expect_next().once().returning(|mut visitor| { // Visit a bool value. visitor.visit_value_and_done(OwnedStatic(false)); // No more fields. Flow::Done }); } // Make a builder for the struct. let mut builder = X::new_builder(); // Visit the sequence of field values. // The struct visitor should report as done. assert!(matches!( visit_sequence(builder.as_visitor(), &mut scope).into_value(), VisitResult::Control(Flow::Done) )); // The builder should be able to build a instance of the struct. assert_eq!( builder.build().into_value().unwrap().0, X { a: true, b: false } ); } #[test] fn a_struct_builder_can_build_from_a_sequence_of_keyed_values() { let mut scope; { // A map is a sequence of keyed values. scope = MockSequenceScope::::new(); // Here we do the b field first to show a map-like doesn't care about order. scope.expect_next().once().returning(|mut visitor| { let mut walker; { walker = MockWalker::<(), (), BlockingSpin>::new(); // We need to give the b field name in the key tag. walker.expect_walk().once().returning(|mut visitor| { visitor.visit_value_and_done(TempBorrowedStatic("b")); Ok(()) }); } // Tag the value with a key as the field name. assert_eq!( visit_tag::(TagConst, visitor.cast(), walker).into_value(), Ok(VisitResult::Control(Flow::Continue)), ); // Visit the value as normal. visitor.visit_value_and_done(OwnedStatic(true)); // There is another field. Flow::Continue }); // The other field. scope.expect_next().once().returning(|mut visitor| { let mut walker; { walker = MockWalker::<(), (), BlockingSpin>::new(); // Here we do field a. walker.expect_walk().once().returning(|mut visitor| { visitor.visit_value_and_done(TempBorrowedStatic("a")); Ok(()) }); } // Tag the value with a key. assert_eq!( visit_tag::(TagConst, visitor.cast(), walker).into_value(), Ok(VisitResult::Control(Flow::Continue)), ); // The field value. visitor.visit_value_and_done(OwnedStatic(false)); // The sequence protocol allows for us to wait to decide if there is another item. Flow::Continue }); // There are no more fields. scope.expect_next().once().returning(|_visitor| Flow::Done); } let mut builder = X::new_builder(); // We need to provide the map tag to the struct before getting into the sequence. // This tag notifies the struct builder to expect the sequence as a map. assert_eq!( visit_tag::(TagConst, builder.as_visitor(), NoopWalker::new()) .into_value(), Ok(VisitResult::Control(Flow::Continue)) ); // Visit the sequence of fields. assert_eq!( visit_sequence(builder.as_visitor(), &mut scope).into_value(), VisitResult::Control(Flow::Done) ); // The struct is built as the mock walker above makes it. assert_eq!( builder.build().into_value().unwrap().0, X { a: false, b: true } ); } */