use std::{future::Future, marker::PhantomData, pin::Pin, thread::yield_now, time::Duration};
use treaty::{
any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId},
build_with, into_walker,
protocol::{
visitor::Value, AnyTraitSendObj, AsyncEffect, ControlFlowFor, Effect, SyncEffect, Visitor, any_t, any_trait_send_obj,
},
Build, Builder, Walker,
};
#[test]
fn demo() {
let hook = Hook {
inner: into_walker(true),
_marker: PhantomData,
};
let x = build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap();
dbg!(x);
todo!();
}
struct Hook<T, Effect> {
inner: T,
_marker: PhantomData<fn() -> Effect>,
}
struct VisitorHook<'a, 'ctx: 'a, E: Effect<'ctx>> {
inner: any_trait_send_obj::T<'a, 'ctx, E::VisitorHkt>,
}
impl<'ctx, T: Walker<'ctx, Effect = AsyncEffect> + Send> Walker<'ctx> for Hook<T, AsyncEffect>
where
<T as Walker<'ctx>>::Error: Send,
<T as Walker<'ctx>>::Output: Send,
{
type Effect = T::Effect;
type Error = T::Error;
type Output = T::Output;
fn walk<'a>(
self,
visitor: Visitor<'a, 'ctx, T::Effect>,
) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error>
where
Self: 'a,
'ctx: 'a
{
Box::pin(async move {
let mut visitor = VisitorHook::<Self::Effect> {
inner: visitor,
};
let flow = self.inner.walk(&mut visitor);
flow.await
})
}
}
impl<'ctx, T: Walker<'ctx, Effect = SyncEffect>> Walker<'ctx> for Hook<T, SyncEffect> {
type Effect = T::Effect;
type Error = T::Error;
type Output = T::Output;
fn walk<'a>(
self,
visitor: Visitor<'a, 'ctx, T::Effect>,
) -> ControlFlowFor<'a, 'ctx, Self::Effect, Self::Output, Self::Error>
where
Self: 'a,
'ctx: 'a,
{
let mut visitor = VisitorHook::<Self::Effect> { inner: visitor };
let flow = self.inner.walk(&mut visitor);
flow
}
}
impl<'b, 'ctx: 'b, E: Effect<'ctx>> AnyTrait<'ctx> for VisitorHook<'b, 'ctx, E> {
fn upcast_to_id<'a>(
&'a self,
id: treaty::any::LtTypeId<'ctx>,
) -> Option<treaty::any::IndirectLtAny<'a, 'ctx, treaty::any::Ref>>
where
'ctx: 'a,
{
match id {
id => self.inner.as_obj().upcast_to_id(id),
}
}
fn upcast_to_id_mut<'a>(
&'a mut self,
id: treaty::any::LtTypeId<'ctx>,
) -> Option<treaty::any::IndirectLtAny<'a, 'ctx, treaty::any::Mut>>
where
'ctx: 'a,
{
match id {
id if id == LtTypeId::of::<dyn Value<'ctx, OwnedStatic<bool>, E> + 'a>() => {
if self.inner.as_obj_mut().upcast_to_id_mut(id).is_some() {
Some(IndirectLtAny::<'a, 'ctx, _>::new::<
dyn Value<'ctx, OwnedStatic<bool>, E> + 'a,
>(self as _))
} else {
None
}
}
id => self.inner.as_obj_mut().upcast_to_id_mut(id),
}
}
}
impl<'b, 'ctx: 'b, E: Effect<'ctx>> Value<'ctx, OwnedStatic<bool>, E> for VisitorHook<'b, 'ctx, E> {
#[inline]
fn visit<'a>(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a, 'ctx, E> where 'ctx: 'a {
let visitor = self
.inner
.as_obj_mut()
.upcast_mut::<dyn Value<'ctx, OwnedStatic<bool>, E> + 'a>()
.unwrap();
println!("Hooked bool: {}", value);
visitor.visit(OwnedStatic(!value))
}
}