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), } } }