use crate::core::*;
use std::marker::PhantomData;
use std::sync::Arc;
pub struct Layer<In, E, Out> {
pub build: Effect<In, E, Env>,
_phantom: PhantomData<Out>,
}
impl<In, E, Out> Clone for Layer<In, E, Out> {
fn clone(&self) -> Self {
Self {
build: self.build.clone(),
_phantom: PhantomData,
}
}
}
impl<In, E, Out> Layer<In, E, Out>
where
In: Clone + Send + Sync + 'static,
E: Send + Sync + 'static,
Out: Send + Sync + 'static,
{
pub fn new(build: Effect<In, E, Env>) -> Self {
Self {
build,
_phantom: PhantomData,
}
}
pub fn succeed<T>(val: T) -> Layer<In, E, T>
where
T: Send + Sync + Clone + 'static,
In: Send + Sync, E: Send + Sync,
{
Layer {
build: Effect::sync(move || {
let mut env = Env::new();
env.insert(val.clone());
env
}),
_phantom: PhantomData,
}
}
pub fn provide_to<A>(self, effect: Effect<Env, E, A>) -> Effect<In, E, A>
where
A: Send + Sync + 'static,
{
self.build.flat_map(move |env| {
let provided = effect.clone().provide(env);
Effect {
inner: Arc::new(move |_env: EnvRef<In>, ctx| {
let provided = provided.clone();
Box::pin(async move { (provided.inner)(EnvRef { value: () }, ctx).await })
}),
}
})
}
}