cocoro 0.3.0

A more type-safe take on Rust stackless coroutines
Documentation
use core::marker::PhantomData;

use crate::coro::Coro;
use crate::suspend::Suspend;
use crate::suspended::Suspended;

pub struct Compose<I, Y1, A, B> {
    a: A,
    b: B,
    _phantom: PhantomData<(I, Y1)>,
}

impl<I, Y1, A, B> Compose<I, Y1, A, B> {
    pub fn new<R, Y2>(a: A, b: B) -> Self
    where
        A: Coro<I, Y1, R>,
        B: Coro<Y1, Y2, R>,
    {
        Compose {
            a,
            b,
            _phantom: PhantomData,
        }
    }
}

impl<I, Y1, Y2, R, A, B> Coro<I, Y2, R> for Compose<I, Y1, A, B>
where
    A: Coro<I, Y1, R>,
    B: Coro<Y1, Y2, R>,
{
    type Next = Compose<I, Y1, A::Next, B::Next>;
    type Suspend = Suspend<Y2, R, Self::Next>;
    fn resume(self, input: I) -> Self::Suspend {
        use Suspend::Return;
        use Suspend::Yield;
        let Compose { a, b, .. } = self;
        match a.resume(input).into_enum() {
            Yield(y, next) => match b.resume(y).into_enum() {
                Yield(y2, next2) => Yield(y2, Compose::new(next, next2)),
                Return(r) => Return(r),
            },
            Return(r) => Return(r),
        }
    }
}