use std::{
future::Future, marker::PhantomData, ops::ControlFlow, pin::Pin, thread::yield_now,
time::Duration,
};
use treaty::{
any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId},
build_with,
effect::{any_t, as_obj, AsObj, AsyncEffect, Effect, EffectAnyTrait, SyncEffect, Yield},
into_walker,
protocol::{visitor::Value, Visitor},
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);
let x = build_with::<<Option<bool> as Build<_>>::Builder, _>(hook).unwrap();
dbg!(x);
todo!();
}
#[no_mangle]
fn invert(x: bool) -> bool {
let hook = Hook {
inner: into_walker(x),
_marker: PhantomData,
};
build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap()
}
struct Hook<T, Effect> {
inner: T,
_marker: PhantomData<fn() -> Effect>,
}
struct VisitorHook<'a, 'ctx: 'a, E: EffectAnyTrait<'ctx>> {
inner: as_obj::T<'a, 'ctx, E::AnyTrait>,
}
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>,
) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
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>,
) -> Yield<'a, 'ctx, Result<Self::Output, Self::Error>, Self::Effect>
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, ControlFlow<(), ()>>> 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),
}
}
#[inline]
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<'a, 'b, 'ctx: 'b + 'a, E: Effect<'ctx, ControlFlow<(), ()>>> Value<'a, 'ctx, OwnedStatic<bool>, E>
for VisitorHook<'b, 'ctx, E>
{
#[inline]
fn visit(
&'a mut self,
OwnedStatic(value): OwnedStatic<bool>,
) -> Yield<'a, 'ctx, ControlFlow<(), ()>, E>
where
'ctx: 'a,
{
let visitor = self
.inner
.as_obj_mut()
.upcast_mut::<dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a>()
.unwrap();
// println!("Hooked bool: {}", value);
visitor.visit(OwnedStatic(!value))
}
}