use std::future::Future;
use std::marker::PhantomData;
use crate::effect::sink::SinkEffect;
use crate::effect::Effect;
#[derive(Debug)]
pub struct Emit<T, E, Env> {
item: T,
_phantom: PhantomData<fn() -> (E, Env)>,
}
impl<T, E, Env> Clone for Emit<T, E, Env>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
item: self.item.clone(),
_phantom: PhantomData,
}
}
}
impl<T, E, Env> Effect for Emit<T, E, Env>
where
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
type Output = ();
type Error = E;
type Env = Env;
async fn run(self, _env: &Self::Env) -> Result<Self::Output, Self::Error> {
Ok(())
}
}
impl<T, E, Env> SinkEffect for Emit<T, E, Env>
where
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
type Item = T;
async fn run_with_sink<S, Fut>(self, _env: &Self::Env, sink: S) -> Result<(), E>
where
S: Fn(Self::Item) -> Fut + Send + Sync,
Fut: Future<Output = ()> + Send,
{
sink(self.item).await;
Ok(())
}
}
pub fn emit<T, E, Env>(item: T) -> Emit<T, E, Env>
where
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
Emit {
item,
_phantom: PhantomData,
}
}
#[derive(Debug)]
pub struct EmitMany<I, T, E, Env> {
items: I,
_phantom_t: PhantomData<fn() -> T>,
_phantom_e: PhantomData<fn() -> E>,
_phantom_env: PhantomData<fn() -> Env>,
}
impl<I, T, E, Env> Clone for EmitMany<I, T, E, Env>
where
I: Clone,
{
fn clone(&self) -> Self {
Self {
items: self.items.clone(),
_phantom_t: PhantomData,
_phantom_e: PhantomData,
_phantom_env: PhantomData,
}
}
}
impl<I, T, E, Env> Effect for EmitMany<I, T, E, Env>
where
I: IntoIterator<Item = T> + Send,
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
type Output = ();
type Error = E;
type Env = Env;
async fn run(self, _env: &Self::Env) -> Result<Self::Output, Self::Error> {
Ok(())
}
}
impl<I, T, E, Env> SinkEffect for EmitMany<I, T, E, Env>
where
I: IntoIterator<Item = T> + Send,
I::IntoIter: Send,
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
type Item = T;
async fn run_with_sink<S, Fut>(self, _env: &Self::Env, sink: S) -> Result<(), E>
where
S: Fn(Self::Item) -> Fut + Send + Sync,
Fut: Future<Output = ()> + Send,
{
for item in self.items {
sink(item).await;
}
Ok(())
}
}
pub fn emit_many<I, T, E, Env>(items: I) -> EmitMany<I, T, E, Env>
where
I: IntoIterator<Item = T> + Send,
T: Send,
E: Send,
Env: Clone + Send + Sync,
{
EmitMany {
items,
_phantom_t: PhantomData,
_phantom_e: PhantomData,
_phantom_env: PhantomData,
}
}