1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
use std::pin::Pin;
/// A trait implemented for coroutines.
///
/// A `Coroutine` is a generalization of a `Generator`. A `Generator` constrains
/// the resume argument type to `()`, but in a `Coroutine` it can be anything.
pub trait Coroutine {
/// The type of value this generator yields.
type Yield;
/// The type of value this generator accepts as a resume argument.
type Resume;
/// The type of value this generator returns upon completion.
type Return;
/// Resumes the execution of this generator.
///
/// The argument will be passed into the coroutine as a resume argument.
fn resume_with(
self: Pin<&mut Self>,
arg: Self::Resume,
) -> GeneratorState<Self::Yield, Self::Return>;
}
/// A trait implemented for generator types.
///
/// This is modeled after the stdlib's nightly-only [`std::ops::Generator`].
pub trait Generator {
/// The type of value this generator yields.
type Yield;
/// The type of value this generator returns upon completion.
type Return;
/// Resumes the execution of this generator.
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return>;
}
impl<C: Coroutine<Resume = ()>> Generator for C {
type Yield = <Self as Coroutine>::Yield;
type Return = <Self as Coroutine>::Return;
#[must_use]
fn resume(self: Pin<&mut Self>) -> GeneratorState<Self::Yield, Self::Return> {
self.resume_with(())
}
}
/// The result of a generator resumption.
///
/// This is modeled after the stdlib's nightly-only
/// [`std::ops::GeneratorState`].
#[derive(PartialEq, Debug)]
#[allow(clippy::module_name_repetitions)]
pub enum GeneratorState<Y, R> {
/// The generator suspended with a value.
Yielded(Y),
/// The generator completed with a return value.
Complete(R),
}