Diffstat (limited to 'tests/hook.rs')
| -rw-r--r-- | tests/hook.rs | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/tests/hook.rs b/tests/hook.rs index e69de29..a7f4509 100644 --- a/tests/hook.rs +++ b/tests/hook.rs @@ -0,0 +1,175 @@ +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, + }, + 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> { + inner: E::Visitor<'a, 'ctx>, +} + +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, Self::Effect, Self::Output, Self::Error> + where + Self: 'a, + { + let visitor: &'a mut (dyn AnyTrait<'ctx> + Send + 'a) = is_send(visitor); + let inner: T = is_send(self.inner); + + let x = async move { + let mut visitor = is_send(VisitorHook::<Self::Effect> { + inner: is_send(visitor), + }); + let flow: Pin< + Box<dyn Future<Output = core::ops::ControlFlow<Self::Error, Self::Output>> + Send>, + > = is_send(is_send(inner).walk(is_send(&mut visitor))); + is_send(assert_send(is_send(flow)).await) + }; + + let y: Pin< + Box<dyn Future<Output = core::ops::ControlFlow<Self::Error, Self::Output>> + Send>, + > = Box::pin(assert_send(x)); + todo!(); + } +} + +pub trait Captures<U> {} +impl<T: ?Sized, U> Captures<U> for T {} + +pub fn make_async<'a, 'ctx, T: Walker<'ctx, Effect = AsyncEffect> + Send + 'a>( + visitor: &'a mut (dyn AnyTrait<'ctx> + Send + 'a), + inner: T, +) -> impl futures::Future<Output = ()> + Send + Captures<&'ctx ()> + 'a +where + AsyncEffect: Send, + T::Error: Send, + T::Output: Send, + T::Effect: Send, +{ + async move { + let mut visitor = is_send(VisitorHook::<AsyncEffect> { + inner: is_send(visitor), + }); + // let flow: Pin<Box<dyn Future<Output = _> + Send>> = + if false { + let _: Pin<Box<dyn Future<Output = _> + Send>> = + is_send(is_send(inner).walk(is_send(todo!()))); + } + tokio::time::sleep(Duration::from_secs(1)).await; + // is_send(assert_send(is_send(flow)).await); + () + } +} + +pub fn is_send<T: Send>(x: T) -> T { + x +} + +pub fn assert_send<T>( + s: impl futures::Future<Output = T> + Send, +) -> impl futures::Future<Output = T> + Send { + s +} + +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, Self::Effect, Self::Output, Self::Error> + where + Self: 'a, + { + let mut visitor = VisitorHook::<Self::Effect> { inner: visitor }; + let flow = self.inner.walk(&mut visitor); + flow + } +} + +impl<'b, 'ctx, E: Effect> 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<'a, OwnedStatic<bool>> + 'a>() => { + if self.inner.as_obj_mut().upcast_to_id_mut(id).is_some() { + Some(IndirectLtAny::<'a, 'ctx, _>::new::< + dyn Value<'a, OwnedStatic<bool>> + 'a, + >(self as _)) + } else { + None + } + } + id => self.inner.as_obj_mut().upcast_to_id_mut(id), + } + } +} + +impl<'a, 'b, 'ctx, E: Effect> Value<'a, OwnedStatic<bool>> for VisitorHook<'b, 'ctx, E> { + #[inline] + fn visit(&'a mut self, OwnedStatic(value): OwnedStatic<bool>) -> ControlFlowFor<'a> { + let visitor = self + .inner + .as_obj_mut() + .upcast_mut::<dyn Value<'a, OwnedStatic<bool>> + 'a>() + .unwrap(); + + println!("Hooked bool: {}", value); + visitor.visit(OwnedStatic(!value)) + } +} |