use std::pin::Pin;
use crate::{Generator, GeneratorState};
struct Iter<G> {
generator: Pin<Box<G>>,
}
pub fn iterate<G>(generator: G) -> impl Iterator<Item = G::Yield>
where
G: Generator,
{
Iter {
generator: Box::pin(generator),
}
}
impl<G> Iterator for Iter<G>
where
G: Generator,
{
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match self.generator.as_mut().resume(()) {
GeneratorState::Yielded(val) => Some(val),
GeneratorState::Complete(_) => None,
}
}
}
struct IterWithReturn<G, F> {
generator: Pin<Box<G>>,
handle_return: Option<F>,
}
pub fn iterate_with_return<G, F>(generator: G, handle_return: F) -> impl Iterator<Item = G::Yield>
where
G: Generator,
F: FnOnce(G::Return) -> Option<G::Yield>,
{
IterWithReturn {
generator: Box::pin(generator),
handle_return: Some(handle_return),
}
}
impl<G, F> Iterator for IterWithReturn<G, F>
where
G: Generator,
F: FnOnce(G::Return) -> Option<G::Yield>,
{
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
if self.handle_return.is_none() {
return None;
}
match self.generator.as_mut().resume(()) {
GeneratorState::Yielded(val) => Some(val),
GeneratorState::Complete(val) => {
if let Some(handle_return) = self.handle_return.take() {
handle_return(val)
} else {
None
}
}
}
}
}