// 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 futures::FutureExt as _;
use pin_project::pin_project;
use crate::hkt::Marker;
use super::{Effect, Effective, ErasedEffective, ErasedForLt, Join, Ss, TryJoin};
pub enum Async {}
pub struct ErasedHrt<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>),
}
pub enum BoxOrReady<'a, T> {
Boxed(Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>),
Ready(T),
}
pub type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + Sync + 'a>>;
impl<'a, T: Ss, O> ErasedForLt<'a, T, Async, &'a (T, O), O> for ErasedHrt<T> {
type T = BoxOrReady<'a, T>;
}
impl<T: Ss> super::ErasedHrt<T, Async> for ErasedHrt<T> {
type T<B> = ErasedHrt<T>;
}
impl Effect for Async {
type Erased<T: Ss> = ErasedHrt<T>;
type Ready<'a, T: Ss + 'a> = Value<T>;
fn ready<'a, T: Ss + 'a>(value: T) -> Self::Ready<'a, T> {
Value(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>
where
F: futures::prelude::Future,
F::Output: Ss + 'a,
{
Shim::new(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> {
self
}
type Effect = Async;
type Output = U;
type IntoFuture = ErasedFuture<'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)),
}
}
type Loop<'ctx: 'a, 'a, T: Ss + 'a, F: Ss + 'a>
= BoxOrReady<'a, (U, T)>
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,
{
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: Ss + 'a, F: Ss + 'a> = Map<ErasedFuture<'lt, U>, F>
where
F: FnOnce(Self::Output) -> T,
'lt: 'a;
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)
}
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)
}))
}
}
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>
where
T0: super::Effective<'a, Effect = Self::Effect>,
T1: super::Effective<'a, Effect = Self::Effect>,
{
Shim::new(futures::future::join(
cb.0.into_future(),
cb.1.into_future(),
))
}
fn three<'a, T0: Ss + 'a, T1: Ss + 'a, T2: Ss + 'a>(
cb: (T0, T1, T2),
) -> Self::Three<'a, T0, T1, T2>
where
T0: super::Effective<'a, Effect = Self::Effect>,
T1: super::Effective<'a, Effect = Self::Effect>,
T2: super::Effective<'a, Effect = Self::Effect>,
{
Shim::new(futures::future::join3(
cb.0.into_future(),
cb.1.into_future(),
cb.2.into_future(),
))
}
}
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>(
cb: (F0, F1),
) -> Self::Two<'a, T0, T1>
where
T0: super::TryEffective<'a, Effect = Self::Effect>,
T1: super::TryEffective<'a, Err = T0::Err, Effect = Self::Effect>,
F0: FnOnce() -> T0,
F1: FnOnce() -> T1,
{
Shim::new(futures::future::try_join(
Box::pin(async { cb.0().into_future().await }),
Box::pin(async { cb.1().into_future().await }),
))
}
fn three<'a, T0: Ss + 'a, T1: Ss + 'a, T2: Ss + 'a, F0: Ss + 'a, F1: Ss + 'a, F2: Ss + 'a>(
cb: (F0, F1, F2),
) -> Self::Three<'a, T0, T1, T2>
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,
{
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;
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),
}
}
}