Diffstat (limited to 'src/effect/async.rs')
-rw-r--r--src/effect/async.rs384
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))
+ })
}
}