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
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
use crate::{GeneratorResult, ValueResult};
use core::num::NonZeroUsize;
use either::Either;

/// Trait for generating values into a closure.
///
/// When a `Generator` is [`run()`](crate::Generator::run) it generates values that are fed an `output` closure.
/// It continues to feed values to the closure for as long as it can, unless the closure returns
/// [`ValueResult::Stop`](crate::ValueResult::Stop).
///
/// When all values have been generated the `run()` method returns [`GeneratorResult::Complete`](crate::GeneratorResult::Complete).
/// If `output` returns [`ValueResult::Stop`](crate::ValueResult::Stop) for any value
/// the generator must not call `output` with any further values and return [`GeneratorResult::Stopped`](crate::GeneratorResult::Stopped)
/// as well.
///
/// **The generator must not assume that it won't be called again after it returns**.
///
/// ## Example
///
/// A generic generator can be written like this:
/// ```
/// use pushgen::{Generator, ValueResult, GeneratorResult};
/// struct GenericGenerator<Out, Gen>
/// where
///     Gen: FnMut() -> Option<Out>,
/// {
///     generator: Gen,
/// }
///
/// impl<Out, Gen> Generator for GenericGenerator<Out, Gen>
///     where
///         Gen: FnMut() -> Option<Out>,
/// {
///     type Output = Out;
///
///     fn run(&mut self, mut output: impl FnMut(Self::Output) -> ValueResult) -> GeneratorResult {
///         while let Some(value) = (self.generator)() {
///             if output(value) == ValueResult::Stop {
///                 return GeneratorResult::Stopped;
///             }
///         }
///         GeneratorResult::Complete
///     }
/// }
/// ```
pub trait Generator {
    /// Data-type generated by the generator.
    type Output;

    /// Run the generator, emitting values to the `output` closure.
    ///
    /// New values are emitted for
    /// as long as the closure returns [`ValueResult::MoreValues`](crate::ValueResult::MoreValues).
    /// If the closure returns [`ValueResult::Stop`](crate::ValueResult::Stop) the generator **must**
    /// return [`GeneratorResult::Stopped`](crate::GeneratorResult::Stopped).
    fn run(&mut self, output: impl FnMut(Self::Output) -> ValueResult) -> GeneratorResult;

    /// Try to advance the generator `n` values, ignoring them.
    ///
    /// This function has a default implementation but should be implemented by adaptors and
    /// source generators for additional performance gains.
    ///
    /// ## Returns
    ///
    /// The number of steps that the generator was actually advanced, and if the generator was
    /// stopped or completed.
    ///
    /// ## Examples
    /// ```
    /// use pushgen::{IntoGenerator, Generator, GeneratorExt, GeneratorResult};
    /// use core::num::NonZeroUsize;
    /// let data = [1, 2, 3, 4, 5];
    /// let mut gen = data.into_gen();
    /// let advance_result = gen.try_advance(NonZeroUsize::new(3).unwrap());
    /// assert_eq!(advance_result, (3, GeneratorResult::Stopped));
    /// assert_eq!(gen.next(), Ok(&4));
    /// assert_eq!(gen.next(), Ok(&5));
    /// ```
    #[inline]
    fn try_advance(&mut self, n: NonZeroUsize) -> (usize, GeneratorResult) {
        let amount_to_advance = n.get();
        let mut amount_left = amount_to_advance;
        let result = self.run(|_| {
            amount_left -= 1;
            if amount_left == 0 {
                ValueResult::Stop
            } else {
                ValueResult::MoreValues
            }
        });

        (amount_to_advance - amount_left, result)
    }
}

impl<L, R> Generator for Either<L, R>
where
    L: Generator,
    R: Generator<Output = L::Output>,
{
    type Output = L::Output;

    #[inline]
    fn run(&mut self, output: impl FnMut(Self::Output) -> ValueResult) -> GeneratorResult {
        match self {
            Either::Left(left) => left.run(output),
            Either::Right(right) => right.run(output),
        }
    }
}