dewit 0.0.1

Define scheduling and execution of code separately from data flow
Documentation
use crate::{
    mode::Mode,
    task::{Task, TaskOutput},
};

struct Join<A, B> {
    a: A,
    b: B,
}

impl<'src, AI, BI, AO, BO, A, B> Task<'src, (AI, BI), (AO, BO)> for Join<A, B>
where
    AI: Send + 'src,
    BI: Send + 'src,
    AO: Send + 'src,
    BO: Send + 'src,
    A: Task<'src, AI, AO> + Send + 'src,
    B: Task<'src, BI, BO> + Send + 'src,
{
    go_impl!('src, (AI, BI), (AO, BO));

    #[inline]
    fn go<M>(self, mode: &'src M, input: (AI, BI)) -> TaskOutput<'src, M, (AO, BO)>
    where
        Self: Sized,
        M: Mode<'src> + Send + Sync,
    {
        mode.join(
            move |mode| self.a.go(mode, input.0),
            move |mode| self.b.go(mode, input.1),
        )
    }
}

/// Combine two tasks by feeding the output of one into the next.
///
/// For ergonomics, [`Task::then`] should be preferred, but until `const` trait
/// functions are stabilized this function permits _constructing_ a [`Task`] to
/// be evaluated at compile time.
#[inline(always)]
pub const fn join<'src, AI, BI, AO, BO>(
    a: impl Task<'src, AI, AO> + Send + 'src,
    b: impl Task<'src, BI, BO> + Send + 'src,
) -> impl Task<'src, (AI, BI), (AO, BO)>
where
    AI: Send + 'src,
    BI: Send + 'src,
    AO: Send + 'src,
    BO: Send + 'src,
{
    Join { a, b }
}