1use std::iter::{Map, Scan, Take, Zip};
2
3#[cfg(test)]
4use std::ops::{Add, Mul};
5
6pub fn option_lift<T: Copy>(f: &dyn Fn(&mut T, T) -> T) -> impl Fn(&mut T, T) -> Option<T> + '_ {
7 |acc, x| {
8 *acc = f(&mut *acc, x);
9 Some(*acc)
10 }
11}
12
13#[cfg(test)]
14fn w<T: Copy, O>(binop: &dyn Fn(T, T) -> O) -> impl Fn(T) -> O + '_ {
15 |x| binop(x, x)
16}
17
18pub trait Iterx: Iterator + Clone {
23 fn drop_last(self) -> Take<Self>
24 where
25 Self: Sized,
26 {
27 let m = self.clone().count() - 1;
28 self.take(m)
29 }
30
31 fn mark_last(self) -> MarkLast<Self> {
32 MarkLast(false, self.peekable())
33 }
34
35 fn scan_<F>(self, f: F) -> Scan_<Self, Self::Item, F>
38 where
39 Self: Sized,
40 F: FnMut(Self::Item, Self::Item) -> Self::Item,
41 {
42 Scan_::new(self, f)
43 }
44
45 fn scan_while<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
47 where
48 Self: Sized,
49 F: FnMut(&mut St, Self::Item) -> Option<B>,
50 {
51 self.scan(initial_state, f)
52 }
53
54 fn prepend(
56 self,
57 value: Self::Item,
58 ) -> std::iter::Chain<std::iter::Once<<Self as Iterator>::Item>, Self>
59 where
60 Self: Sized,
61 {
62 std::iter::once(value).chain(self)
63 }
64
65 fn prescan<St, F>(self, initial_state: St, f: F) -> Prescan<Self, St, F>
67 where
68 Self: Sized,
69 F: FnMut(St, Self::Item) -> St,
70 {
71 Prescan::new(self, initial_state, f)
72 }
73
74 fn zip_map<U, T, F>(
76 self,
77 other: U,
78 f: F,
79 ) -> Map<
80 Zip<Self, U::IntoIter>,
81 Box<dyn Fn((<Self as Iterator>::Item, <U as IntoIterator>::Item)) -> T>,
82 >
83 where
84 Self: Sized,
85 U: IntoIterator,
86 F: Fn(<Self as Iterator>::Item, <U as IntoIterator>::Item) -> T + 'static,
87 {
88 self.zip(other.into_iter())
89 .map(Box::new(move |(x, y)| f(x, y)))
90 }
91}
92
93impl<T: ?Sized + std::clone::Clone> Iterx for T where T: Iterator {}
94
95#[derive(Clone)]
96pub struct Prescan<I, St, F> {
97 iter: I,
98 f: F,
99 state: Option<St>,
100}
101
102impl<I, St, F> Prescan<I, St, F> {
103 fn new(iter: I, initial_state: St, f: F) -> Self {
104 Self {
105 iter,
106 f,
107 state: Some(initial_state),
108 }
109 }
110}
111
112impl<I, St: Clone, F> Iterator for Prescan<I, St, F>
113where
114 I: Iterator,
115 F: FnMut(St, I::Item) -> St,
116{
117 type Item = St;
118
119 fn next(&mut self) -> Option<Self::Item> {
120 let state = self.state.take()?;
121
122 if let Some(x) = self.iter.next() {
123 self.state = Some((self.f)(state.clone(), x));
124 }
125
126 Some(state)
127 }
128
129 fn size_hint(&self) -> (usize, Option<usize>) {
130 let (lb, ub) = self.iter.size_hint();
131 (lb + 1, ub.map(|ub| ub + 1))
132 }
133}
134
135#[derive(Clone)]
136pub struct Scan_<I, T, F> {
137 iter: I,
138 f: F,
139 state: Option<T>,
140 is_first: bool,
141}
142
143impl<I, T, F> Scan_<I, T, F>
144where
145 I: Iterator<Item = T>,
146{
147 fn new(iter: I, f: F) -> Self {
148 Self {
149 iter,
150 f,
151 state: None,
152 is_first: true,
153 }
154 }
155}
156
157impl<I, T: Clone, F> Iterator for Scan_<I, T, F>
158where
159 I: Iterator<Item = T>,
160 F: FnMut(T, T) -> T,
161{
162 type Item = T;
163
164 fn next(&mut self) -> Option<Self::Item> {
165 if self.is_first {
166 self.state = Some(self.iter.next())?;
167 self.is_first = false;
168 }
169
170 let state = self.state.take()?;
171
172 if let Some(x) = self.iter.next() {
173 self.state = Some((self.f)(state.clone(), x));
174 }
175
176 Some(state)
177 }
178
179 fn size_hint(&self) -> (usize, Option<usize>) {
180 self.iter.size_hint()
181 }
182}
183
184pub struct MarkLast<I>(bool, std::iter::Peekable<I>)
185where
186 I: Iterator;
187
188impl<I> Iterator for MarkLast<I>
189where
190 I: Iterator,
191{
192 type Item = (bool, I::Item);
193
194 fn next(&mut self) -> Option<Self::Item> {
195 self.1.next().map(|e| (self.1.peek().is_none(), e))
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202
203 use itertools::assert_equal;
204
205 #[test]
206 fn test_scan_while() {
207 assert_equal(
208 vec![1, 1, 1]
209 .into_iter()
210 .scan_while(0, &option_lift(&|a, b| *a + b)),
211 1..=3,
212 );
213 }
214
215 #[test]
216 fn test_w_combinator() {
217 assert_eq!(w(&Add::add)(1), 2);
218 }
219
220 #[test]
221 fn test_scan_() {
222 assert_equal(vec![1].into_iter().scan_(|x, y| x + y), 1..2);
223 assert_equal(vec![1, 1, 1].into_iter().scan_(|x, y| x + y), 1..=3);
225 assert_equal((1..=5).scan_(|x, y| x + y), vec![1, 3, 6, 10, 15]);
226 }
227
228 #[test]
229 fn test_prescan() {
230 assert_equal(vec![1].into_iter().prescan(0, |x, y| x + y), 0..=1);
231 assert_equal(vec![1, 1, 1].into_iter().prescan(0, |x, y| x + y), 0..=3);
232 assert_equal((1..=5).prescan(0, |x, y| x + y), vec![0, 1, 3, 6, 10, 15]);
233 assert_equal((1..=5).prescan(0, |x, y| x + y).skip(2), vec![3, 6, 10, 15]);
234 }
235
236 #[test]
237 fn test_zip_map() {
238 assert_equal((1..5).zip_map(1..5, |a, b| a + b), vec![2, 4, 6, 8]);
239 assert_equal((1..5).zip_map(1..5, &Add::add), vec![2, 4, 6, 8]);
240 assert_equal((1..5).zip_map(1..5, |a, b| a * b), vec![1, 4, 9, 16]);
241 assert_equal((1..5).zip_map(1..5, &Mul::mul), vec![1, 4, 9, 16]);
242 assert_equal((1..5).zip_map(2..6, &std::cmp::max), 2..6);
243 assert_equal((1..5).zip_map(2..6, &std::cmp::min), 1..5);
244 }
245
246 #[test]
247 fn test_drop_last() {
248 assert_equal((1..4).drop_last(), vec![1, 2]);
249 assert_equal((1..5).drop_last(), vec![1, 2, 3]);
250 }
251
252 #[test]
253 fn test_prepend() {
254 assert_equal((1..4).prepend(0), 0..4);
255 assert_equal((2..5).prepend(1), 1..5);
256 }
257
258 #[test]
259 fn test_mark_last() {
260 assert_equal((1..3).mark_last(), vec![(false, 1), (true, 2)]);
261 assert_equal((1..4).mark_last(), vec![(false, 1), (false, 2), (true, 3)]);
262 }
263}