Diffstat (limited to 'tests/hook.rs')
-rw-r--r--tests/hook.rs175
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))
+ }
+}