Diffstat (limited to 'src/effect/async/shim.rs')
| -rw-r--r-- | src/effect/async/shim.rs | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/effect/async/shim.rs b/src/effect/async/shim.rs new file mode 100644 index 0000000..fcc16ae --- /dev/null +++ b/src/effect/async/shim.rs @@ -0,0 +1,112 @@ +use core::ops::ControlFlow; + +use futures::Future; + +use crate::effect::{Effective, ErasedEffective}; + +use super::{Async, BoxOrReady, Map, Then}; + +pub struct Shim<F> { + future: F, +} + +impl<F> Shim<F> { + pub(super) fn new(future: F) -> Self { + Self { future } + } +} + +impl<'lt, U: Send + Sync + 'lt> Effective<'lt> for Shim<U> +where + U: Future, + U::Output: Send + Sync + 'lt, +{ + fn into_erased<B>(self) -> ErasedEffective<'lt, Self::Output, Self::Effect, B> { + BoxOrReady::Boxed(Box::pin(self.future)) + } + + type Effect = Async; + + type Output = U::Output; + + type IntoFuture = U; + + fn into_future(self) -> Self::IntoFuture { + self.future + } + + type Loop<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a> + = BoxOrReady<'a, (U::Output, T)> + where + F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect, (&'b mut Self::Output, &'ctx ())>, + 'lt: 'a; + + fn r#loop<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, mut cb: F) -> Self::Loop<'ctx, 'a, T, F> + where + F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect, (&'b mut Self::Output, &'ctx ())>, + 'lt: 'a, + { + BoxOrReady::Boxed(Box::pin(async move { + let mut this = self.into_future().await; + + loop { + if let ControlFlow::Break(value) = cb(&mut this).into_future().await { + return (this, value); + } + } + })) + } + + type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a> + = Map<U, F> + where + F: FnOnce(Self::Output) -> T, + 'lt: 'a; + + fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F> + where + F: FnOnce(Self::Output) -> T, + 'lt: 'a, + { + Map::new(self.future, cb) + } + + type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a> + = Then<'a, U, F, V> + where + F: FnOnce(Self::Output) -> V, + V: Effective<'a, Output = T, Effect = Self::Effect>, + 'lt: 'a; + + fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>( + self, + cb: F, + ) -> Self::Then<'a, T, V, F> + where + F: FnOnce(Self::Output) -> V, + V: Effective<'a, Output = T, Effect = Self::Effect>, + 'lt: 'a, + { + Then::new(self.future, cb) + } + + type AsCtx<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a> + = BoxOrReady<'a, (Self::Output, T)> + where + F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>, + 'lt: 'a; + + fn as_ctx<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'ctx, 'a, T, F> + where + F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect>, + 'lt: 'a, + { + BoxOrReady::Boxed(Box::pin(async { + let mut this = self.future.await; + + let result = cb(&mut this).into_future().await; + + (this, result) + })) + } +} |