Diffstat (limited to 'src/effect/async.rs')
| -rw-r--r-- | src/effect/async.rs | 384 |
1 files changed, 192 insertions, 192 deletions
diff --git a/src/effect/async.rs b/src/effect/async.rs index 1c0eb9d..fd0bbf0 100644 --- a/src/effect/async.rs +++ b/src/effect/async.rs @@ -1,78 +1,85 @@ -// mod join; -// mod try_join; -mod map; -mod shim; -mod then; -mod value; - -// pub use join::*; -// pub use try_join::*; -pub use map::*; -pub use shim::*; -pub use then::*; -pub use value::*; - -use core::{ops::ControlFlow, pin::Pin}; - -use core::future::Future; +use core::pin::Pin; use futures::FutureExt as _; use pin_project::pin_project; use crate::hkt::Marker; -use super::{Effect, Effective, ErasedEffective, ErasedForLt, Join, Ss, TryJoin}; +use super::*; pub enum Async {} -pub struct ErasedHrt<T>(Marker<T>); +pub struct ErasedFutureHrt<T>(Marker<T>); -#[pin_project(project = ErasedFutureProj)] -pub enum ErasedFuture<'a, T> { - Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>), - Ready(#[pin] core::future::Ready<T>), +enum ErasedFutureKind<'lt, T> { + Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'lt>>), + Ready(T), } -pub enum BoxOrReady<'a, T> { - Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>), - Ready(T), +pub struct ErasedFuture<'lt, T> { + kind: ErasedFutureKind<'lt, T>, } -pub type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>; +#[pin_project(project = EffectFutureKindProj)] +enum EffectFutureKind<'lt, T> { + Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'lt>>), + Ready(#[pin] ::core::future::Ready<T>), +} -impl<'a, T: Ss, O> ErasedForLt<'a, T, Async, &'a (T, O)> for ErasedHrt<T> { - type T = BoxOrReady<'a, T>; +#[pin_project] +pub struct EffectFuture<'lt, T> { + #[pin] + kind: EffectFutureKind<'lt, T>, } -impl<T: Ss> super::ErasedHrt<T, Async> for ErasedHrt<T> { - type T<B> = ErasedHrt<T>; +impl<'lt, T> Future for EffectFuture<'lt, T> { + type Output = T; + + fn poll( + self: Pin<&mut Self>, + cx: &mut core::task::Context<'_>, + ) -> core::task::Poll<Self::Output> { + let this = self.project(); + match this.kind.project() { + EffectFutureKindProj::Boxed(fut) => fut.poll_unpin(cx), + EffectFutureKindProj::Ready(fut) => fut.poll(cx), + } + } } -impl Effect for Async { - type Erased<T: Ss> = ErasedHrt<T>; +impl<'lt, T: Ss, O> Erased::ForLt<'lt, T, Async, &'lt (T, O)> for ErasedFutureHrt<T> { + type Effective = ErasedFuture<'lt, T>; +} + +impl<T: Ss> Erased::Hkt<T, Async> for ErasedFutureHrt<T> { + type Hrt<O> = Self; +} - type Ready<'a, T: Ss + 'a> = Value<T>; +impl Effect for Async { + type Erased<T: Ss> = ErasedFutureHrt<T>; - fn ready<'a, T: Ss + 'a>(value: T) -> Self::Ready<'a, T> { - Value(value) + fn ready<'a, T: Ss + 'a>(value: T) -> ErasedEffective<'a, T, Self> { + ErasedFuture { + kind: ErasedFutureKind::Ready(value), + } } - type FromFuture<'a, F: Ss + 'a> = Shim<F> - where - F: futures::prelude::Future, - F::Output: Ss + 'a; - - fn from_future<'a, F: Ss + 'a>(future: F) -> Self::FromFuture<'a, F> + fn from_future<'a, F>(future: F) -> ErasedEffective<'a, F::Output, Self> where - F: futures::prelude::Future, + F: Future + Ss + 'a, F::Output: Ss + 'a, { - Shim::new(future) + ErasedFuture { + kind: ErasedFutureKind::Boxed(Box::pin(future)), + } } } -impl<'lt, U: Ss + 'lt> Effective<'lt> for BoxOrReady<'lt, U> { - fn into_erased<B>(self) -> super::ErasedEffective<'lt, Self::Output, Self::Effect, B> { +impl<'lt, U: Ss + 'lt> Effective<'lt> for ErasedFuture<'lt, U> { + fn cast<'wrap, X>(self) -> ErasedEffective<'wrap, Self::Output, Self::Effect, X> + where + 'lt: 'wrap, + { self } @@ -80,190 +87,183 @@ impl<'lt, U: Ss + 'lt> Effective<'lt> for BoxOrReady<'lt, U> { type Output = U; - type IntoFuture = ErasedFuture<'lt, U>; + type IntoFuture = EffectFuture<'lt, U>; fn into_future(self) -> Self::IntoFuture { - match self { - BoxOrReady::Boxed(fut) => ErasedFuture::Boxed(fut), - BoxOrReady::Ready(value) => ErasedFuture::Ready(core::future::ready(value)), + EffectFuture { + kind: match self.kind { + ErasedFutureKind::Boxed(fut) => EffectFutureKind::Boxed(fut), + ErasedFutureKind::Ready(value) => { + EffectFutureKind::Ready(::core::future::ready(value)) + } + }, } } - type Loop<'ctx: 'a, 'a, T: Ss + 'a, F: Ss + 'a> - = BoxOrReady<'a, (U, T)> + fn r#do< + 'ctx: 'lt, + 'wrap, + Pre, + Ctx, + Owned, + First, + FirstOutput, + FirstPost, + Done, + Extra, + Repeat, + RepeatOutput, + RepeatPost, + Post, + Return, + >( + self, + pre: Pre, + first: First, + first_post: FirstPost, + mut repeat: Repeat, + mut repeat_post: RepeatPost, + post: Post, + ) -> ErasedEffective<'wrap, Return, Self::Effect> where - F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect>, - 'lt: 'a; - - fn r#loop<'ctx: 'a, 'a, T: Ss + 'a, F: Ss + '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>, - 'lt: 'a, + Pre: Ss + 'wrap + FnOnce(Self::Output) -> (Ctx, ControlFlow<Done, Owned>), + First: Ss + + 'wrap + + for<'b> FnOnce( + &'b mut Ctx, + Owned, + ) -> ErasedEffective<'b, FirstOutput, Self::Effect, &'wrap ()>, + FirstPost: + Ss + 'wrap + for<'b> FnOnce(&'b mut Ctx, FirstOutput) -> ControlFlow<Done, Extra>, + Repeat: Ss + + 'wrap + + for<'b> FnMut( + &'b mut Ctx, + &'b mut Extra, + ) -> ErasedEffective<'b, RepeatOutput, Self::Effect, &'wrap ()>, + RepeatPost: Ss + + 'wrap + + for<'b> FnMut(&'b mut Ctx, &'b mut Extra, RepeatOutput) -> ControlFlow<Done>, + Post: 'wrap + Ss + FnOnce(Ctx, Option<Extra>, Done) -> Return, + Return: Ss, + FirstOutput: Ss, + RepeatOutput: Ss, + Owned: Ss, + Done: Ss, + Ctx: Ss, + Extra: Ss, + 'lt: 'wrap, { - 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); + let fut = async move { + let (ctx, done, extra) = match pre(self.into_future().await) { + (mut ctx, ControlFlow::Continue(owned)) => { + let first_output = first(&mut ctx, owned).into_future().await; + + let (done, extra) = match first_post(&mut ctx, first_output) { + ControlFlow::Continue(mut extra) => loop { + let repeat_output = repeat(&mut ctx, &mut extra).into_future().await; + + match repeat_post(&mut ctx, &mut extra, repeat_output) { + ControlFlow::Continue(()) => {} + ControlFlow::Break(done) => break (done, Some(extra)), + } + }, + ControlFlow::Break(done) => (done, None), + }; + + (ctx, done, extra) } - } - })) - } + (ctx, ControlFlow::Break(done)) => (ctx, done, None), + }; - type Map<'a, T: Ss + 'a, F: Ss + 'a> = Map<ErasedFuture<'lt, U>, F> - where - F: FnOnce(Self::Output) -> T, - 'lt: 'a; + post(ctx, extra, done) + }; - fn map<'a, T: Ss + 'a, F: Ss + 'a>(self, cb: F) -> Self::Map<'a, T, F> - where - F: FnOnce(Self::Output) -> T, - 'lt: 'a, - { - Map::new(self.into_future(), cb) - } - - type Then<'a, T: Ss + 'a, V: Ss + 'a, F: Ss + 'a> - = Then<'a, ErasedFuture<'lt, U>, F, V> - where - F: FnOnce(Self::Output) -> V, - V: Effective<'a, Output = T, Effect = Self::Effect>, - 'lt: 'a; - - fn then<'a, T: Ss + 'a, V: Ss + 'a, F: Ss + '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.into_future(), cb) + ErasedFuture { + kind: ErasedFutureKind::Boxed(Box::pin(fut)), + } } - type AsCtx<'ctx: 'a, 'a, T: Ss + 'a, F: Ss + 'a> - = BoxOrReady<'a, (Self::Output, T)> - where - F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>, - 'lt: 'a; - - fn as_ctx<'ctx: 'a, 'a, T: Ss + 'a, F: Ss + 'a>(self, cb: F) -> Self::AsCtx<'ctx, 'a, T, F> - where - F: for<'b> FnOnce(&'b mut Self::Output) -> super::ErasedEffective<'b, T, Self::Effect>, - 'lt: 'a, - { - BoxOrReady::Boxed(Box::pin(async { - let mut this = self.into_future().await; - - let result = cb(&mut this).into_future().await; - - (this, result) - })) + fn ready(value: Self::Output) -> Self { + ErasedFuture { + kind: ErasedFutureKind::Ready(value), + } } } impl Join for Async { type Effect = Self; - type Two<'a, T0: Ss + 'a, T1: Ss + 'a> - = Shim<futures::future::Join<T0::IntoFuture, T1::IntoFuture>> - where - T0: super::Effective<'a, Effect = Self::Effect>, - T1: super::Effective<'a, Effect = Self::Effect>; - - type Three<'a, T0: Ss + 'a, T1: Ss + 'a, T2: Ss + 'a> - = Shim<futures::future::Join3<T0::IntoFuture, T1::IntoFuture, T2::IntoFuture, >> - where - T0: super::Effective<'a, Effect = Self::Effect>, - T1: super::Effective<'a, Effect = Self::Effect>, - T2: super::Effective<'a, Effect = Self::Effect>; - - fn two<'a, T0: Ss + 'a, T1: Ss + 'a>(cb: (T0, T1)) -> Self::Two<'a, T0, T1> + fn two<'a, T0, T1>( + effectives: (T0, T1), + ) -> ErasedEffective<'a, (T0::Output, T1::Output), Self::Effect> where - T0: super::Effective<'a, Effect = Self::Effect>, - T1: super::Effective<'a, Effect = Self::Effect>, + T0: Ss + 'a + Effective<'a, Effect = Self::Effect>, + T1: Ss + 'a + Effective<'a, Effect = Self::Effect>, { - Shim::new(futures::future::join( - cb.0.into_future(), - cb.1.into_future(), - )) + Self::from_future(async { + let v0 = effectives.0.into_future().await; + let v1 = effectives.1.into_future().await; + + (v0, v1) + }) } - fn three<'a, T0: Ss + 'a, T1: Ss + 'a, T2: Ss + 'a>( - cb: (T0, T1, T2), - ) -> Self::Three<'a, T0, T1, T2> + fn three<'a, T0, T1, T2>( + effectives: (T0, T1, T2), + ) -> ErasedEffective<'a, (T0::Output, T1::Output, T2::Output), Self::Effect> where - T0: super::Effective<'a, Effect = Self::Effect>, - T1: super::Effective<'a, Effect = Self::Effect>, - T2: super::Effective<'a, Effect = Self::Effect>, + T0: Ss + 'a + Effective<'a, Effect = Self::Effect>, + T1: Ss + 'a + Effective<'a, Effect = Self::Effect>, + T2: Ss + 'a + Effective<'a, Effect = Self::Effect>, { - Shim::new(futures::future::join3( - cb.0.into_future(), - cb.1.into_future(), - cb.2.into_future(), - )) + Self::from_future(async { + let v0 = effectives.0.into_future().await; + let v1 = effectives.1.into_future().await; + let v2 = effectives.2.into_future().await; + + (v0, v1, v2) + }) } } impl TryJoin for Async { type Effect = Self; - type Two<'a, T0: Ss + 'a, T1: Ss + 'a> - = Shim<futures::future::TryJoin<BoxedFuture<'a, T0::Output>, BoxedFuture<'a, T1::Output>>> - where - T0: super::TryEffective<'a, Effect = Self::Effect>, - T1: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>; - - type Three<'a, T0: Ss + 'a, T1: Ss + 'a, T2: Ss + 'a> - = Shim<futures::future::TryJoin3<BoxedFuture<'a, T0::Output>, BoxedFuture<'a, T1::Output>, BoxedFuture<'a, T2::Output>>> - where - T0: super::TryEffective<'a, Effect = Self::Effect>, - T1: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, - T2: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>; - - fn two<'a, T0: Ss + 'a, T1: Ss + 'a, F0: Ss + 'a, F1: Ss + 'a>( + fn two<'a, T0, T1, F0, F1>( cb: (F0, F1), - ) -> Self::Two<'a, T0, T1> + ) -> ErasedEffective<'a, Result<(T0::Ok, T1::Ok), T0::Err>, Self::Effect> where - T0: super::TryEffective<'a, Effect = Self::Effect>, - T1: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, - F0: FnOnce() -> T0, - F1: FnOnce() -> T1, + T0: Ss + 'a + TryEffective<'a, Effect = Self::Effect>, + T1: Ss + 'a + TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, + F0: Ss + 'a + FnOnce() -> T0, + F1: Ss + 'a + FnOnce() -> T1, { - Shim::new(futures::future::try_join( - Box::pin(async { cb.0().into_future().await }), - Box::pin(async { cb.1().into_future().await }), - )) + Self::from_future(async { + let v0 = cb.0().into_future().await?; + let v1 = cb.1().into_future().await?; + + Ok((v0, v1)) + }) } - fn three<'a, T0: Ss + 'a, T1: Ss + 'a, T2: Ss + 'a, F0: Ss + 'a, F1: Ss + 'a, F2: Ss + 'a>( + fn three<'a, T0, T1, T2, F0, F1, F2>( cb: (F0, F1, F2), - ) -> Self::Three<'a, T0, T1, T2> + ) -> ErasedEffective<'a, Result<(T0::Ok, T1::Ok, T2::Ok), T0::Err>, Self::Effect> where - T0: super::TryEffective<'a, Effect = Self::Effect>, - T1: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, - T2: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, - F0: FnOnce() -> T0, - F1: FnOnce() -> T1, - F2: FnOnce() -> T2, + T0: Ss + 'a + TryEffective<'a, Effect = Self::Effect>, + T1: Ss + 'a + TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, + T2: Ss + 'a + TryEffective<'a, Err = T0::Err, Effect = Self::Effect>, + F0: Ss + 'a + FnOnce() -> T0, + F1: Ss + 'a + FnOnce() -> T1, + F2: Ss + 'a + FnOnce() -> T2, { - Shim::new(futures::future::try_join3( - Box::pin(async { cb.0().into_future().await }), - Box::pin(async { cb.1().into_future().await }), - Box::pin(async { cb.2().into_future().await }), - )) - } -} - -impl<'lt, T> Future for ErasedFuture<'lt, T> { - type Output = T; + Self::from_future(async { + let v0 = cb.0().into_future().await?; + let v1 = cb.1().into_future().await?; + let v2 = cb.2().into_future().await?; - fn poll( - self: Pin<&mut Self>, - cx: &mut core::task::Context<'_>, - ) -> core::task::Poll<Self::Output> { - match self.project() { - ErasedFutureProj::Boxed(fut) => fut.poll_unpin(cx), - ErasedFutureProj::Ready(fut) => fut.poll(cx), - } + Ok((v0, v1, v2)) + }) } } |