flowly-service 0.6.0

Flowly is a library of modular and reusable components for building robust pipelines processing audio, video and other.
Documentation
use std::marker::PhantomData;

use futures::{FutureExt, Stream, StreamExt, TryStreamExt};

use crate::Service;

pub fn scope<I, M, E, S, F>(f: F, service: S) -> Scope<I, M, E, S, F> {
    Scope {
        service,
        f,
        _m: PhantomData,
    }
}

pub fn scope_each<I: Clone, M, S, F, E>(f: F, service: S) -> ScopeEach<I, M, S, F, E> {
    ScopeEach {
        service,
        f,
        _m: PhantomData,
    }
}

#[derive(Clone)]
pub struct Scope<I, M, E, S, F> {
    service: S,
    f: F,
    _m: PhantomData<(I, M, E)>,
}

impl<I, M, E1, O, E, S, F> Service<I> for Scope<I, M, E1, S, F>
where
    S: Service<M, Out = Result<O, E>> + Send,
    F: Send + Fn(&I) -> Result<M, E1> + Sync,
    M: Send + Sync,
    O: Send,
    I: Send + Sync,
    E: Send + Sync + From<E1>,
    E1: Send + Sync,
{
    type Out = Result<(I, Vec<O>), E>;

    fn handle(&self, msg: I, cx: &crate::Context) -> impl Stream<Item = Self::Out> + Send {
        async move {
            match (self.f)(&msg) {
                Ok(m) => self
                    .service
                    .handle(m, cx)
                    .try_collect()
                    .await
                    .map(move |dat| (msg, dat)),
                Err(err) => Err(E::from(err)),
            }
        }
        .into_stream()
    }
}

#[derive(Clone)]
pub struct ScopeEach<I, M, S, F, E> {
    service: S,
    f: F,
    _m: PhantomData<(I, M, E)>,
}

impl<I, M, O, E, E1, S, F> Service<I> for ScopeEach<I, M, S, F, E1>
where
    S: Service<M, Out = Result<O, E>> + Send,
    F: Send + Sync + Fn(&I) -> Result<M, E1>,
    M: Send + Sync,
    O: Send,
    I: Send + Clone + Sync + 'static,
    E: Send + Sync + From<E1>,
    E1: Send + Sync,
{
    type Out = Result<(I, O), E>;

    fn handle(&self, msg: I, cx: &crate::Context) -> impl Stream<Item = Self::Out> + Send {
        async move {
            match (self.f)(&msg) {
                Ok(m) => Ok(self
                    .service
                    .handle(m, cx)
                    .map(move |x| x.map(|x| (msg.clone(), x)))),
                Err(err) => Err(E::from(err)),
            }
        }
        .into_stream()
        .try_flatten()
    }
}