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)
}))
}
}