use effectful::{
blocking::BlockingSpin,
bound::{Bool, Dynamic, IsSend, IsSync},
effective::{Canonical, Effective},
environment::Environment,
forward_send_sync, DynBind,
};
use mockall::mock;
use treaty::{
any::{type_name, AnyTrait, OwnedStatic},
protocol::{
visitor::{visit_value, Value, VisitResult},
AsVisitor, DynVisitor,
},
Flow,
};
mock! {
pub ValueVisitor<T: type_name::Static>
where
for<'a, 'ctx> type_name::Lowered<'a, 'ctx, T>: Sized
{
pub fn visit<'a, 'ctx>(&'a mut self, value: &type_name::Lowered<'a, 'ctx, T>) -> VisitResult<()>;
}
}
forward_send_sync!({} {} {T: (type_name::Static + Send)} MockValueVisitor<T> where {
for<'a, 'ctx> type_name::Lowered<'a, 'ctx, T>: Sized
});
// any_trait! {
// impl['ctx, T][E] MockValueVisitor<T, E> = [
// ValueProto<T, E>
// ] where
// T: TypeName::MemberType<E>,
// for<'a, 'b> TypeName::T<'a, 'b, T, E>: Sized,
// for<'a> Dynamic<TypeName::T<'a, 'ctx, T, E>>: DynBind<E>,
// E: Environment,
// }
impl<'ctx, T: type_name::Static + Send, E: Environment> Value<'ctx, T, E> for MockValueVisitor<T>
where
for<'a, 'b> type_name::Lowered<'a, 'b, T>: Sized,
{
fn visit<'r>(
&'r mut self,
value: type_name::Lowered<'r, 'ctx, T>,
) -> Canonical<'r, VisitResult<type_name::Lowered<'r, 'ctx, T>>, E>
where
// type_name::Lowered<'value, 'ctx, T>: Sized,
type_name::Lowered<'r, 'ctx, T>: DynBind<E>,
{
todo!()
}
// fn visit<'a>(
// &'a mut self,
// value: TypeName::T<'a, 'ctx, T, E>,
// ) -> Canonical<'a, VisitResult<Dynamic<TypeName::T<'a, 'ctx, T, E>>>, E>
// where
// 'ctx: 'a,
// {
// E::value(match self.visit(&value) {
// VisitResult::Skipped(_) => VisitResult::Skipped(Dynamic(value)),
// VisitResult::Control(flow) => VisitResult::Control(flow),
// })
// .cast()
// }
}
pub trait ValueVisitorExt<'ctx> {
fn visit_value_and_done<'a, T>(&'a mut self, value: T)
where
T: type_name::WithLt<'a, 'ctx> + DynBind<BlockingSpin>,
type_name::Raised<'a, 'ctx, T>: type_name::Static,
'ctx: 'a;
fn visit_value_and_skipped<'a, T>(&'a mut self, value: T)
where
T: type_name::WithLt<'a, 'ctx>,
type_name::Raised<'a, 'ctx, T>: type_name::Static,
'ctx: 'a;
}
impl<'ctx, U> ValueVisitorExt<'ctx> for U
where
U: AsVisitor<'ctx, BlockingSpin>,
{
#[track_caller]
fn visit_value_and_done<'a, T>(&'a mut self, value: T)
where
T: type_name::WithLt<'a, 'ctx> + DynBind<BlockingSpin>,
type_name::Raised<'a, 'ctx, T>: type_name::Static,
'ctx: 'a,
{
let result = visit_value::<_, BlockingSpin>(self.as_visitor(), value).wait();
assert_eq!(result, VisitResult::Control(Flow::Done));
}
#[track_caller]
fn visit_value_and_skipped<'a, T>(&'a mut self, value: T)
where
T: type_name::WithLt<'a, 'ctx>,
type_name::Raised<'a, 'ctx, T>: type_name::Static,
'ctx: 'a,
{
todo!()
}
// #[track_caller]
// fn visit_value_and_done<'a, T>(&'a mut self, value: T)
// where
// T: TypeName::LowerType<'a, 'ctx, BlockingSpin>,
// TypeName::HigherRanked<'a, 'ctx, T, BlockingSpin>: TypeName::MemberType<BlockingSpin>,
// 'ctx: 'a,
// {
// let result = visit_value::<_, BlockingSpin>(self.as_visitor(), value).into_value();
//
// assert_eq!(result, VisitResult::Control(Flow::Done));
// }
//
// #[track_caller]
// fn visit_value_and_skipped<'a, T>(&'a mut self, value: T)
// where
// T: TypeName::LowerType<'a, 'ctx, BlockingSpin>,
// TypeName::HigherRanked<'a, 'ctx, T, BlockingSpin>: TypeName::MemberType<BlockingSpin>,
// 'ctx: 'a,
// {
// let result = visit_value::<_, BlockingSpin>(self.as_visitor(), value).into_value();
//
// assert_eq!(result.unit_skipped(), VisitResult::Skipped(()));
// }
}