Diffstat (limited to 'src/protocol.rs')
-rw-r--r--src/protocol.rs78
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")
+ }
}