alternating_iter/
alternating_no_remainder.rs

1use core::iter;
2
3use crate::utils::{checked, min_and_1, saturating};
4#[allow(unused_imports)]
5use crate::AlternatingExt;
6
7/// Struct for alternating between the items of two iterators until one is exhausted.
8///
9/// This struct is created by the [`AlternatingExt::alternate_with_no_remainder`] method, see its documentation for more.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct AlternatingNoRemainder<I, J> {
12    i: I,
13    j: J,
14    last_i: bool,
15}
16
17impl<I, J> AlternatingNoRemainder<I, J>
18where
19    I: Iterator,
20    J: Iterator<Item = I::Item>,
21{
22    /// Create a new `AlternatingNoRemainder` iterator from two other iterables.
23    ///
24    /// Alternative to [`AlternatingExt::alternate_with_no_remainder`]. There is no  difference.
25    pub fn new(i: impl IntoIterator<IntoIter = I>, j: impl IntoIterator<IntoIter = J>) -> Self {
26        Self {
27            i: i.into_iter(),
28            j: j.into_iter(),
29            last_i: false,
30        }
31    }
32}
33
34impl<I, J> Iterator for AlternatingNoRemainder<I, J>
35where
36    I: Iterator,
37    J: Iterator<Item = I::Item>,
38{
39    type Item = I::Item;
40    fn next(&mut self) -> Option<Self::Item> {
41        if self.last_i {
42            if let Some(item) = self.j.next() {
43                self.last_i = false;
44                Some(item)
45            } else {
46                None
47            }
48        } else {
49            if let Some(item) = self.i.next() {
50                self.last_i = true;
51                Some(item)
52            } else {
53                None
54            }
55        }
56    }
57
58    fn size_hint(&self) -> (usize, Option<usize>) {
59        let (i_lower, i_upper) = self.i.size_hint();
60        let (j_lower, j_upper) = self.j.size_hint();
61
62        // The longest we can go without outputing consecutive elements
63        // from the same iterator is twice the length of the shorter iterator.
64        // We can squeeze 1 more if the other iterator is longer and
65        // the last element was from the same iterator.
66
67        let lower = saturating(min_and_1(i_lower, j_lower, self.last_i));
68        let upper = match (i_upper, j_upper) {
69            (Some(i_upper), Some(j_upper)) => checked(min_and_1(i_upper, j_upper, self.last_i)),
70            (Some(i_upper), None) => checked((i_upper, self.last_i)),
71            (None, Some(j_upper)) => checked((j_upper, !self.last_i)),
72            // Since both have no upper bound, as far as we are concerned,
73            // this mean they go on forever. Therefore, we don't have to worry
74            // about one of them running out.
75            (None, None) => None,
76        };
77        (lower, upper)
78    }
79}
80
81// Deprecated: According to the documentation for ExactSizeIterator,
82// "If an adapter makes an iterator longer, then it’s usually incorrect for
83// that adapter to implement ExactSizeIterator."
84
85// impl<I, J> iter::ExactSizeIterator for AlternatingNoRemainder<I, J>
86// where
87//     I: iter::ExactSizeIterator,
88//     J: iter::ExactSizeIterator<Item = I::Item>,
89// {
90//     fn len(&self) -> usize {
91//         saturating(min_and_1(self.i.len(), self.j.len(), self.last_i))
92//     }
93// }
94impl<I, J> iter::FusedIterator for AlternatingNoRemainder<I, J>
95where
96    I: iter::FusedIterator,
97    J: iter::FusedIterator<Item = I::Item>,
98{
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[test]
106    fn is_fused() {
107        let a = 1..3;
108        let b = iter::repeat(0);
109
110        let mut iter = a.alternate_with_no_remainder(b);
111
112        assert_eq!(iter.next(), Some(1));
113        assert_eq!(iter.next(), Some(0));
114        assert_eq!(iter.next(), Some(2));
115        assert_eq!(iter.next(), Some(0));
116        assert_eq!(iter.next(), None);
117        assert_eq!(iter.next(), None);
118        assert_eq!(iter.next(), None);
119    }
120
121    #[test]
122    fn same_lengths() {
123        let a = [1, 2];
124        let b = [3, 4];
125
126        let mut iter = a.iter().alternate_with_no_remainder(b.iter());
127
128        assert_eq!(iter.next(), Some(&1));
129        assert_eq!(iter.next(), Some(&3));
130        assert_eq!(iter.next(), Some(&2));
131        assert_eq!(iter.next(), Some(&4));
132        assert_eq!(iter.next(), None);
133    }
134
135    #[test]
136    fn different_lengths_1more() {
137        let a = [1, 2];
138        let b = [3, 4, 5];
139
140        let mut iter = a.iter().alternate_with_no_remainder(b.iter());
141
142        assert_eq!(iter.next(), Some(&1));
143        assert_eq!(iter.next(), Some(&3));
144        assert_eq!(iter.next(), Some(&2));
145        assert_eq!(iter.next(), Some(&4));
146        assert_eq!(iter.next(), None);
147    }
148
149    #[test]
150    fn different_lengths_2more() {
151        let a = [1, 2];
152        let b = [3, 4, 5, 6];
153
154        let mut iter = a.iter().alternate_with_no_remainder(b.iter());
155
156        assert_eq!(iter.next(), Some(&1));
157        assert_eq!(iter.next(), Some(&3));
158        assert_eq!(iter.next(), Some(&2));
159        assert_eq!(iter.next(), Some(&4));
160        assert_eq!(iter.next(), None);
161    }
162
163    #[test]
164    fn empty_iterators() {
165        let a: [i32; 0] = [];
166        let b: [i32; 0] = [];
167
168        let mut iter = a.iter().alternate_with_no_remainder(b.iter());
169
170        assert_eq!(iter.next(), None);
171    }
172
173    #[test]
174    fn one_empty_iterator() {
175        let a = [1, 2, 3];
176        let b: [i32; 0] = [];
177
178        let mut iter = a.iter().alternate_with_no_remainder(b.iter());
179
180        assert_eq!(iter.next(), Some(&1));
181        assert_eq!(iter.next(), None);
182    }
183
184    #[test]
185    fn same_iterator() {
186        let a = [1, 2, 3];
187
188        let mut iter = a.iter().alternate_with_no_remainder(a.iter());
189
190        assert_eq!(iter.next(), Some(&1));
191        assert_eq!(iter.next(), Some(&1));
192        assert_eq!(iter.next(), Some(&2));
193        assert_eq!(iter.next(), Some(&2));
194        assert_eq!(iter.next(), Some(&3));
195        assert_eq!(iter.next(), Some(&3));
196        assert_eq!(iter.next(), None);
197    }
198
199    #[test]
200    fn size_hint_accurate() {
201        let a = [1, 2, 3];
202        let b = [4, 5];
203
204        assert_eq!(
205            a.iter().size_hint().1,
206            Some(a.iter().count()),
207            "Sanity check failed"
208        );
209        assert_eq!(
210            b.iter().size_hint().1,
211            Some(b.iter().count()),
212            "Sanity check failed"
213        );
214
215        let iter = a.iter().alternate_with_no_remainder(b.iter());
216
217        assert_eq!(iter.size_hint().1, Some(iter.count()));
218    }
219    #[test]
220    fn size_hint() {
221        let a = [1, 2, 3];
222        let b = [4, 5];
223
224        assert_eq!(a.iter().size_hint(), (3, Some(3)), "Sanity check failed");
225        assert_eq!(b.iter().size_hint(), (2, Some(2)), "Sanity check failed");
226
227        let iter = a.iter().alternate_with_no_remainder(b.iter());
228
229        assert_eq!(iter.size_hint(), (5, Some(5)));
230        assert_eq!(iter.count(), 5, "Inaccurate size hint");
231    }
232    #[test]
233    fn size_hint_unbounded_right() {
234        let a = [1, 2, 3];
235        let b = iter::repeat(&0);
236
237        assert_eq!(a.iter().size_hint(), (3, Some(3)), "Sanity check failed");
238        assert_eq!(b.size_hint(), (usize::MAX, None), "Sanity check failed");
239
240        let iter = a.iter().alternate_with_no_remainder(b);
241
242        assert_eq!(iter.size_hint(), (6, Some(6)));
243        assert_eq!(iter.count(), 6, "Inaccurate size hint");
244    }
245    #[test]
246    fn size_hint_unbounded_left() {
247        let a = iter::repeat(&0);
248        let b = [1, 2, 3];
249
250        assert_eq!(a.size_hint(), (usize::MAX, None), "Sanity check failed");
251        assert_eq!(b.iter().size_hint(), (3, Some(3)), "Sanity check failed");
252
253        let iter = a.alternate_with_no_remainder(b.iter());
254
255        assert_eq!(iter.size_hint(), (7, Some(7)));
256        assert_eq!(iter.count(), 7, "Inaccurate size hint");
257    }
258    #[test]
259    fn size_hint_bound_exceed_max() {
260        let a = 0..usize::MAX;
261        let b = 0..usize::MAX;
262
263        assert_eq!(
264            a.size_hint(),
265            (usize::MAX, Some(usize::MAX)),
266            "Sanity check failed"
267        );
268        assert_eq!(
269            b.size_hint(),
270            (usize::MAX, Some(usize::MAX)),
271            "Sanity check failed"
272        );
273
274        let iter = a.alternate_with_no_remainder(b);
275
276        assert_eq!(iter.size_hint(), (usize::MAX, None));
277    }
278    #[test]
279    fn size_hint_bound_half_max_left() {
280        let a = 0..usize::MAX / 2;
281        let b = 0..usize::MAX / 2 + 1;
282
283        assert_eq!(
284            a.size_hint(),
285            (usize::MAX / 2, Some(usize::MAX / 2)),
286            "Sanity check failed"
287        );
288        assert_eq!(
289            b.size_hint(),
290            (usize::MAX / 2 + 1, Some(usize::MAX / 2 + 1)),
291            "Sanity check failed"
292        );
293
294        let iter = a.alternate_with_no_remainder(b);
295
296        assert_eq!(iter.size_hint(), (usize::MAX - 1, Some(usize::MAX - 1)));
297    }
298    #[test]
299    fn size_hint_bound_half_max_right() {
300        let a = 0..usize::MAX / 2 + 1;
301        let b = 0..usize::MAX / 2;
302
303        assert_eq!(
304            a.size_hint(),
305            (usize::MAX / 2 + 1, Some(usize::MAX / 2 + 1)),
306            "Sanity check failed"
307        );
308        assert_eq!(
309            b.size_hint(),
310            (usize::MAX / 2, Some(usize::MAX / 2)),
311            "Sanity check failed"
312        );
313
314        let iter = a.alternate_with_no_remainder(b);
315
316        assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX)));
317    }
318    #[test]
319    fn size_hint_both_unbounded() {
320        let a = iter::repeat(0);
321        let b = iter::repeat(0);
322
323        assert_eq!(a.size_hint(), (usize::MAX, None), "Sanity check failed");
324        assert_eq!(b.size_hint(), (usize::MAX, None), "Sanity check failed");
325
326        let iter = a.alternate_with_no_remainder(b);
327
328        assert_eq!(iter.size_hint(), (usize::MAX, None));
329    }
330}