cocoro 0.3.0

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

use either::Either;

use crate::Coro;
use crate::FixedPointCoro;
use crate::Suspend;
use crate::Suspend::Return;
use crate::Suspend::Yield;
use crate::Suspended;
use crate::weave;

struct Weaving<Src, Processor, Cont, P> {
    src: Src,
    processor: Processor,
    cont: Cont,
    phantom: P,
}

impl<I, Y, A, X, R, Src, Worker, Start, Processor, Finish, Transition, Cont>
    Coro<A, X, R>
    for Weaving<
        Src,
        Processor,
        Cont,
        PhantomData<(I, Y, Worker, Start, Transition)>,
    >
where
    Src: FixedPointCoro<I, Y, R>,
    Worker: FixedPointCoro<Y, I, X>,
    Start: Suspended<Y, I, X, Next = Worker>,
    Processor: Coro<A, Start, R>,
    Finish: Coro<A, X, R>,
    Transition: Suspended<A, X, R, Next = Finish>,
    Cont: FnOnce(R, Worker) -> Transition,
{
    type Next = Either<
        Weaving<
            Src,
            Processor::Next,
            Cont,
            PhantomData<(I, Y, Worker, Start, Transition)>,
        >,
        Finish,
    >;
    type Suspend = Suspend<X, R, Self::Next>;
    fn resume(self, a: A) -> Self::Suspend {
        use Either::*;
        let Self {
            src,
            processor,
            cont,
            phantom,
        } = self;
        match processor.resume(a).into_enum() {
            Yield(start, processor) => match start.into_enum() {
                Yield(i, worker) => match weave(src, worker, i) {
                    Left((r, worker)) => match cont(r, worker).into_enum() {
                        Yield(x, finish) => Yield(x, Right(finish)),
                        Return(r) => Return(r),
                    },
                    Right((x, src)) => Yield(
                        x,
                        Left(Weaving {
                            src,
                            processor,
                            cont,
                            phantom,
                        }),
                    ),
                },
                Return(x) => Yield(
                    x,
                    Left(Weaving {
                        src,
                        processor,
                        cont,
                        phantom,
                    }),
                ),
            },
            Return(r) => Return(r),
        }
    }
}

pub fn process<
    I,
    Y,
    R,
    A,
    X,
    Src,
    Worker,
    Start,
    Processor,
    Finish,
    Transition,
>(
    src: Src,
    processor: Processor,
    cont: impl FnOnce(R, Worker) -> Transition,
) -> impl Coro<A, X, R>
where
    Src: FixedPointCoro<I, Y, R>,
    Worker: FixedPointCoro<Y, I, X>,
    Start: Suspended<Y, I, X, Next = Worker>,
    Processor: Coro<A, Start, R>,
    Finish: Coro<A, X, R>,
    Transition: Suspended<A, X, R, Next = Finish>,
{
    Weaving {
        src,
        processor,
        cont,
        phantom: PhantomData,
    }
}