use core::{
marker::Unpin,
ops::{Generator, GeneratorState},
pin::Pin,
};
pub struct SimpleGenIterator<G>(pub(crate) G);
pub trait SupportedReturnValue {}
impl SupportedReturnValue for () {}
impl SupportedReturnValue for ! {}
impl<G> Iterator for SimpleGenIterator<G>
where
G: Generator<()> + Unpin,
G::Return: SupportedReturnValue,
{
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match Pin::new(&mut self.0).resume(()) {
GeneratorState::Yielded(y) => Some(y),
GeneratorState::Complete(_) => None,
}
}
}
pub struct RawGenIterator<G> {
pub(crate) gen: G,
}
impl<G> Iterator for RawGenIterator<G>
where
G: Generator<()> + Unpin,
{
type Item = GeneratorState<G::Yield, G::Return>;
fn next(&mut self) -> Option<Self::Item> {
Some(Pin::new(&mut self.gen).resume(()))
}
}
pub enum FusedGenIterator<G: Generator<()>> {
Generator(G),
Completed(G::Return),
}
impl<G: Generator<()> + Unpin> FusedGenIterator<G> {
pub(crate) fn new(g: G) -> Self {
FusedGenIterator::Generator(g)
}
pub fn is_completed(&self) -> bool {
matches!(self, FusedGenIterator::Generator(_))
}
#[track_caller]
pub fn into_return(self) -> G::Return {
match self {
FusedGenIterator::Completed(c) => c,
FusedGenIterator::Generator(_) => {
panic!("into_return called, but generator has not completed yat")
}
}
}
}
impl<G: Generator<()> + Unpin> Iterator for FusedGenIterator<G> {
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
let gen = match self {
FusedGenIterator::Generator(gen) => Pin::new(gen),
FusedGenIterator::Completed(_) => return None,
};
match gen.resume(()) {
GeneratorState::Yielded(y) => Some(y),
GeneratorState::Complete(c) => {
*self = FusedGenIterator::Completed(c);
None
}
}
}
}
impl<G: Generator<()> + Unpin> core::iter::FusedIterator for FusedGenIterator<G> {}