use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use crate::effect::trait_def::Effect;
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub struct BoxedEffect<T, E, Env> {
run_fn: Box<dyn FnOnce(Env) -> BoxFuture<'static, Result<T, E>> + Send>,
_phantom: PhantomData<Env>,
}
impl<T, E, Env> std::fmt::Debug for BoxedEffect<T, E, Env> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BoxedEffect")
.field("run_fn", &"<function>")
.finish()
}
}
impl<T, E, Env> BoxedEffect<T, E, Env>
where
T: Send + 'static,
E: Send + 'static,
Env: Clone + Send + Sync + 'static,
{
pub fn new<Eff>(effect: Eff) -> Self
where
Eff: Effect<Output = T, Error = E, Env = Env> + 'static,
{
BoxedEffect {
run_fn: Box::new(move |env: Env| {
Box::pin(async move { effect.run(&env).await })
}),
_phantom: PhantomData,
}
}
}
impl<T, E, Env> Effect for BoxedEffect<T, E, Env>
where
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
type Output = T;
type Error = E;
type Env = Env;
fn run(self, env: &Env) -> impl Future<Output = Result<T, E>> + Send {
let env_owned = env.clone(); (self.run_fn)(env_owned)
}
}
pub struct BoxedLocalEffect<T, E, Env> {
#[allow(clippy::type_complexity)]
run_fn: Box<dyn FnOnce(Env) -> Pin<Box<dyn Future<Output = Result<T, E>> + 'static>>>,
_phantom: PhantomData<Env>,
}
impl<T, E, Env> std::fmt::Debug for BoxedLocalEffect<T, E, Env> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BoxedLocalEffect")
.field("run_fn", &"<function>")
.finish()
}
}
impl<T, E, Env> BoxedLocalEffect<T, E, Env>
where
T: 'static,
E: 'static,
Env: Clone + 'static,
{
pub fn new<Eff>(effect: Eff) -> Self
where
Eff: Effect<Output = T, Error = E, Env = Env> + 'static,
Eff::Output: 'static,
Eff::Error: 'static,
{
BoxedLocalEffect {
run_fn: Box::new(move |env: Env| Box::pin(async move { effect.run(&env).await })),
_phantom: PhantomData,
}
}
pub fn run_local(self, env: &Env) -> Pin<Box<dyn Future<Output = Result<T, E>> + 'static>> {
let env_owned = env.clone();
(self.run_fn)(env_owned)
}
}