Diffstat (limited to 'src/protocol.rs')
| -rw-r--r-- | src/protocol.rs | 78 |
1 files changed, 72 insertions, 6 deletions
diff --git a/src/protocol.rs b/src/protocol.rs index 26ec664..37bcee7 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -33,26 +33,58 @@ //! This is done via the help of the [`AnyImpl`] type. This is not required for the core //! idea of DIDETs. +use core::{ + future::Future, + pin::{pin, Pin}, + ptr, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, +}; + use crate::any::AnyTrait; pub mod visitor; pub mod walker; -#[cfg(not(feature = "std"))] +#[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::boxed::Box; -pub type Visitor<'ctx> = dyn AnyTrait<'ctx>; -pub type Walker<'ctx> = dyn AnyTrait<'ctx>; +pub type Visitor<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a; +pub type Walker<'a, 'ctx> = dyn AnyTrait<'ctx> + 'a; + +pub trait Effect: 'static { + type ControlFlow<'a, C, B>: Future<Output = core::ops::ControlFlow<B, C>>; -pub trait Effect { - type ControlFlow<'a, C, B>; + fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( + future: F, + ) -> Self::ControlFlow<'a, C, B>; } + pub type ControlFlowFor<'a, E = SyncEffect, C = (), B = ()> = <E as Effect>::ControlFlow<'a, C, B>; pub enum SyncEffect {} impl Effect for SyncEffect { - type ControlFlow<'a, C, B> = core::ops::ControlFlow<B, C>; + type ControlFlow<'a, C, B> = Ready<core::ops::ControlFlow<B, C>>; + + fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( + future: F, + ) -> Self::ControlFlow<'a, C, B> { + let pinned_future = pin!(future); + + let waker = noop(); + let mut cx = Context::<'_>::from_waker(&waker); + match pinned_future.poll(&mut cx) { + Poll::Ready(value) => Ready::new(value), + Poll::Pending => panic!("expected future to be ready"), + } + } +} + +fn noop() -> Waker { + const VTABLE: RawWakerVTable = RawWakerVTable::new(|_| RAW, |_| {}, |_| {}, |_| {}); + const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); + + unsafe { Waker::from_raw(RAW) } } #[cfg(feature = "alloc")] @@ -62,4 +94,38 @@ pub enum AsyncEffect {} impl Effect for AsyncEffect { type ControlFlow<'a, C, B> = core::pin::Pin<Box<dyn core::future::Future<Output = core::ops::ControlFlow<B, C>> + 'a>>; + + fn wrap<'a, C, B, F: Future<Output = core::ops::ControlFlow<B, C>> + 'a>( + future: F, + ) -> Self::ControlFlow<'a, C, B> { + Box::pin(future) + } +} + +#[must_use] +pub struct Ready<T>(Option<T>); + +impl<T> Unpin for Ready<T> {} + +impl<T> Future for Ready<T> { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> { + unsafe { + Poll::Ready(self.0.take().unwrap_unchecked()) + } + } +} + +impl<T> Ready<T> { + pub fn new(value: T) -> Self { + Self(Some(value)) + } + + #[must_use] + pub fn into_inner(self) -> T { + unsafe { self.0.unwrap_unchecked() } + // .expect("Called `into_inner()` on `Ready` after completion") + } } |