generate 1.5.0

Provides compatability layers for `std::ops::Generator` on stable rust.
Documentation
use std::pin::Pin;

use crate::{Generator, GeneratorState};

struct Iter<G> {
    generator: Pin<Box<G>>,
}

/// Turns the given generator into an iterator.
///
/// The returned iterator iterates over `Generator::Yield` and returns `None` when
/// `GeneratorState::Complete(_)` is returned.
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>,
}
/// Turns the given generator into an iterator, with a function to handle the
/// `GeneratorState::Complete(_)` case.
///
/// The returned iterator iterates over `Generator::Yield`. When `GeneratorState::Complete(_)`
/// is returned, it calls `handle_return` with the returned value. The return of that call is then
/// emitted from the iterator. All subsequent calls to `Iterator::next` then return `None`.
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
                }
            }
        }
    }
}