use std::{marker::PhantomData, ops::ControlFlow, pin::Pin, thread::yield_now, time::Duration};
use treaty::{
any::{any_trait, static_wrapper::OwnedStatic, AnyTrait, IndirectLtAny, LtTypeId},
builders::core::option::IgnoreMissing,
effect::{BlockOn, Blocking, Effect, Future, Spin},
protocol::visitor::value::Value,
protocol::Visitor,
transform, Build, Builder, Walk, Walker, WalkerTypes,
};
#[test]
fn demo() {
let hook = Hook::<_, Blocking> {
inner: true.into_walker::<Blocking>(),
_marker: PhantomData,
};
// let x = build_with::<<bool as Build<_>>::Builder, _>(hook).unwrap();
// dbg!(x);
// let x = Spin::block_on(transform::<<Option<bool> as Build>::Builder<_>, _, Blocking>(IgnoreMissing::No, hook));
let x = Spin::block_on(transform::<<bool as Build>::Builder<_>, _, Blocking>(
(),
hook,
));
dbg!(x);
todo!();
}
#[no_mangle]
fn invert(x: bool) -> bool {
let hook = Hook::<_, Blocking> {
inner: x.into_walker::<Blocking>(),
_marker: PhantomData,
};
Spin::block_on(transform::<<bool as Build>::Builder<_>, _, Blocking>(
(),
hook,
))
.0
.unwrap()
}
struct Hook<T, E> {
inner: T,
_marker: PhantomData<fn() -> E>,
}
struct VisitorHook<'a, 'ctx: 'a, E> {
inner: Visitor<'a, 'ctx>,
_marker: PhantomData<fn() -> E>,
}
impl<'ctx, T: Walker<'ctx, Effect = E>, E: Effect<'ctx>> WalkerTypes<'ctx> for Hook<T, E> {
type Error = T::Error;
type Output = T::Output;
}
impl<'ctx, T: Walker<'ctx, Effect = E>, E: Effect<'ctx>> Walker<'ctx> for Hook<T, E> {
type Effect = E;
fn walk<'a>(
self,
visitor: Visitor<'a, 'ctx>,
) -> Future<'a, 'ctx, Result<Self::Output, Self::Error>, E>
where
Self: 'a,
{
E::wrap(async {
let mut visitor = VisitorHook::<E> {
inner: visitor,
_marker: PhantomData,
};
let flow = self.inner.walk(&mut visitor);
flow.await
})
}
}
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.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<'a, 'ctx, OwnedStatic<bool>, E> + 'a>() => {
// println!("hook: {:?}", id);
if self.inner.upcast_to_id_mut(id).is_some() {
Some(IndirectLtAny::<'a, 'ctx, _>::new::<
dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a,
>(self as _))
} else {
None
}
}
id => {
// println!("fallback: {:?}", id);
self.inner.upcast_to_id_mut(id)
}
}
}
}
impl<'a, 'b, 'ctx: 'a + 'b, E: Effect<'ctx>> Value<'a, 'ctx, OwnedStatic<bool>, E>
for VisitorHook<'b, 'ctx, E>
{
#[inline]
fn visit(
&'a mut self,
OwnedStatic(value): OwnedStatic<bool>,
) -> Future<'a, 'ctx, ControlFlow<(), ()>, E> {
let visitor = self
.inner
.upcast_mut::<dyn Value<'a, 'ctx, OwnedStatic<bool>, E> + 'a>()
.unwrap();
// println!("Hooked bool: {}", value);
visitor.visit(OwnedStatic(!value))
}
}