1use crate::{Generator, GeneratorResult, ValueResult};
2use core::num::NonZeroUsize;
3
4#[derive(Clone)]
6pub struct Skip<Gen> {
7 generator: Gen,
8 amount: usize,
9}
10
11impl<Gen> Skip<Gen> {
12 #[inline]
13 pub(crate) fn new(generator: Gen, amount: usize) -> Self {
14 Self { generator, amount }
15 }
16}
17
18impl<Gen> Generator for Skip<Gen>
19where
20 Gen: Generator,
21{
22 type Output = Gen::Output;
23
24 #[inline]
25 fn run(&mut self, mut output: impl FnMut(Self::Output) -> ValueResult) -> GeneratorResult {
26 if self.amount > 0 {
27 match self
29 .generator
30 .try_advance(unsafe { core::num::NonZeroUsize::new_unchecked(self.amount) })
31 {
32 (_, GeneratorResult::Complete) => {
33 self.amount = 0;
34 return GeneratorResult::Complete;
35 }
36 (x, _) => {
37 self.amount -= x;
38 if self.amount != 0 {
39 return GeneratorResult::Stopped;
40 }
41 }
42 }
43 }
44
45 self.generator.run(|value| output(value))
46 }
47
48 #[inline]
49 fn try_advance(&mut self, n: NonZeroUsize) -> (usize, GeneratorResult) {
50 if self.amount > 0 {
51 match self
52 .generator
53 .try_advance(unsafe { NonZeroUsize::new_unchecked(self.amount) })
54 {
55 (_, GeneratorResult::Complete) => {
56 self.amount = 0;
57 return (0, GeneratorResult::Complete);
58 }
59 (x, _) => {
60 self.amount -= x;
61 if self.amount != 0 {
62 return (0, GeneratorResult::Stopped);
63 }
64 }
65 }
66 }
67
68 self.generator.try_advance(n)
69 }
70}
71
72#[derive(Clone)]
73pub struct SkipWhile<Src, P> {
74 source: Src,
75 predicate: P,
76 need_skip_run: bool,
77}
78
79impl<Src, P> SkipWhile<Src, P>
80where
81 Src: Generator,
82 P: FnMut(&Src::Output) -> bool,
83{
84 #[inline]
85 pub(crate) fn new(source: Src, predicate: P) -> Self {
86 Self {
87 source,
88 predicate,
89 need_skip_run: true,
90 }
91 }
92}
93
94impl<Src, P> Generator for SkipWhile<Src, P>
95where
96 Src: Generator,
97 P: FnMut(&Src::Output) -> bool,
98{
99 type Output = Src::Output;
100
101 #[inline]
102 fn run(&mut self, mut output: impl FnMut(Self::Output) -> ValueResult) -> GeneratorResult {
103 if self.need_skip_run {
104 let mut first_to_push = None;
105 let predicate = &mut self.predicate;
106
107 let skip_run_result = self.source.run(|x| {
108 if predicate(&x) {
109 ValueResult::MoreValues
110 } else {
111 first_to_push = Some(x);
112 ValueResult::Stop
113 }
114 });
115
116 if skip_run_result == GeneratorResult::Complete {
117 return GeneratorResult::Complete;
118 } else if let Some(x) = first_to_push {
119 self.need_skip_run = false;
120 if output(x) == ValueResult::Stop {
121 return GeneratorResult::Stopped;
122 }
123 } else {
124 return GeneratorResult::Stopped;
125 }
126 }
127 self.source.run(|x| output(x))
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134 use crate::test::StoppingGen;
135 use crate::{GeneratorExt, IntoGenerator};
136
137 #[test]
138 fn skip() {
139 let a = [1, 2, 3];
140
141 let mut gen = Skip::new(a.into_gen(), 2);
142 let mut output = Vec::new();
143 let result = gen.for_each(|x| output.push(x));
144 assert_eq!(output, [&3]);
145 assert_eq!(result, GeneratorResult::Complete);
146 }
147
148 #[test]
149 fn spuriously_stopping_skip() {
150 let data = [1, 2, 3, 4, 5];
151 for x in 0..5 {
152 let mut gen = StoppingGen::new(x, &data).skip(3);
153 let mut output = Vec::new();
154 let result = gen.for_each(|x| output.push(x));
155 assert_eq!(result, GeneratorResult::Stopped);
156 let result = gen.for_each(|x| output.push(x));
157 assert_eq!(result, GeneratorResult::Complete);
158 assert_eq!(output, [&4, &5]);
159 }
160 }
161
162 #[test]
163 fn skip_while() {
164 let a = [-1i32, 0, 1];
165
166 let mut gen = SkipWhile::new(a.into_gen(), |x| x.is_negative());
167 let mut output = Vec::new();
168 let result = gen.for_each(|x| output.push(x));
169 assert_eq!(output, [&0, &1]);
170 assert_eq!(result, GeneratorResult::Complete);
171 }
172
173 #[test]
174 fn spuriously_stopping_skip_while() {
175 let data = [-1i32, -2, 0, -1, 2];
176 for x in 0..5 {
177 let mut gen = StoppingGen::new(x, &data).skip_while(|x| x.is_negative());
178 let mut output = Vec::new();
179 let result = gen.for_each(|x| output.push(x));
180 assert_eq!(result, GeneratorResult::Stopped);
181 let result = gen.for_each(|x| output.push(x));
182 assert_eq!(result, GeneratorResult::Complete);
183 assert_eq!(output, [&0, &-1, &2]);
184 }
185 }
186
187 #[test]
188 fn try_advance() {
189 let data = [0, 1, 2, 3, 4, 5, 6, 7, 8];
190 let mut gen = data.into_gen().skip(3);
191 let result = gen.try_advance(NonZeroUsize::new(2).unwrap());
192 assert_eq!(result, (2, GeneratorResult::Stopped));
193 assert_eq!(gen.next(), Ok(&5));
194 }
195
196 #[test]
197 fn try_advance_stopping_skip_region() {
198 let data = [0, 1, 2, 3, 4, 5, 6, 7, 8];
199 let mut gen = StoppingGen::new(1, &data).skip(3);
200 let result = gen.try_advance(NonZeroUsize::new(2).unwrap());
201 assert_eq!(result, (0, GeneratorResult::Stopped));
202 let result = gen.try_advance(NonZeroUsize::new(2).unwrap());
203 assert_eq!(result, (2, GeneratorResult::Stopped));
204 assert_eq!(gen.next(), Ok(&5));
205 }
206
207 #[test]
208 fn try_advance_stopping() {
209 let data = [0, 1, 2, 3, 4, 5, 6, 7, 8];
210 let mut gen = StoppingGen::new(4, &data).skip(3);
211 let result = gen.try_advance(NonZeroUsize::new(2).unwrap());
212 assert_eq!(result, (1, GeneratorResult::Stopped));
213 let result = gen.try_advance(NonZeroUsize::new(1).unwrap());
214 assert_eq!(result, (1, GeneratorResult::Stopped));
215 assert_eq!(gen.next(), Ok(&5));
216 }
217
218 #[test]
219 fn try_advance_max() {
220 let data = [0, 1, 2, 3, 4, 5, 6, 7, 8];
221 let mut gen = data.into_gen().skip(3);
222 let result = gen.try_advance(NonZeroUsize::new(usize::MAX).unwrap());
223 assert_eq!(result, (6, GeneratorResult::Complete));
224 }
225}