use crate::{
core::{advance, async_advance, Airlock as _, Next},
ops::{Coroutine, GeneratorState},
rc::{engine::Airlock, Co},
};
use std::{future::Future, pin::Pin};
pub struct Gen<Y, R, F: Future> {
airlock: Airlock<Y, R>,
future: Pin<Box<F>>,
}
impl<Y, R, F: Future> Gen<Y, R, F> {
pub fn new(producer: impl FnOnce(Co<Y, R>) -> F) -> Self {
let airlock = Airlock::default();
let future = { Box::pin(producer(Co::new(airlock.clone()))) };
Self { airlock, future }
}
pub fn resume_with(&mut self, arg: R) -> GeneratorState<Y, F::Output> {
self.airlock.replace(Next::Resume(arg));
advance(self.future.as_mut(), &self.airlock)
}
}
impl<Y, F: Future> Gen<Y, (), F> {
pub fn resume(&mut self) -> GeneratorState<Y, F::Output> {
self.resume_with(())
}
pub fn async_resume(
&mut self,
) -> impl Future<Output = GeneratorState<Y, F::Output>> + '_ {
self.airlock.replace(Next::Resume(()));
async_advance(self.future.as_mut(), self.airlock.clone())
}
}
impl<Y, R, F: Future> Coroutine for Gen<Y, R, F> {
type Yield = Y;
type Resume = R;
type Return = F::Output;
fn resume_with(
mut self: Pin<&mut Self>,
arg: R,
) -> GeneratorState<Self::Yield, Self::Return> {
Self::resume_with(&mut *self, arg)
}
}