alternating_iter/
alternating_all.rs

1use core::iter;
2
3#[allow(unused_imports)]
4use crate::AlternatingExt;
5
6/// Struct for alternating between the items of two iterators while handling size difference intuitively.
7///
8/// This struct is created by the [`AlternatingExt::alternate_with_all`] method, see its documentation for more.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct AlternatingAll<I, J> {
11    i: I,
12    j: J,
13    next: Next,
14}
15
16/// Represent the next iterator to be used.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18enum Next {
19    I,
20    J,
21    /// Marks that iterator `j` has been exhausted
22    IAlways,
23    /// Marks that iterato `i` has been exhausted
24    JAlways,
25}
26
27impl<I, J> AlternatingAll<I, J>
28where
29    I: Iterator,
30    J: Iterator<Item = I::Item>,
31{
32    /// Create a new `AlternatingAll` iterator from two other iterables.
33    ///
34    /// Alternative to [`AlternatingExt::alternate_with_all`]. There is no significant difference.
35    pub fn new(i: impl IntoIterator<IntoIter = I>, j: impl IntoIterator<IntoIter = J>) -> Self {
36        Self {
37            i: i.into_iter(),
38            j: j.into_iter(),
39            next: Next::I,
40        }
41    }
42}
43
44impl<I, J> Iterator for AlternatingAll<I, J>
45where
46    I: Iterator,
47    J: Iterator<Item = I::Item>,
48{
49    type Item = I::Item;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        match self.next {
53            Next::I => {
54                if let Some(item) = self.i.next() {
55                    self.next = Next::J;
56                    Some(item)
57                } else {
58                    self.next = Next::JAlways;
59                    self.j.next()
60                }
61            }
62            Next::J => {
63                if let Some(item) = self.j.next() {
64                    self.next = Next::I;
65                    Some(item)
66                } else {
67                    self.next = Next::IAlways;
68                    self.i.next()
69                }
70            }
71            Next::IAlways => self.i.next(),
72            Next::JAlways => self.j.next(),
73        }
74    }
75
76    fn size_hint(&self) -> (usize, Option<usize>) {
77        let (i_lower, i_upper) = self.i.size_hint();
78        let (j_lower, j_upper) = self.j.size_hint();
79        (
80            usize::saturating_add(i_lower, j_lower),
81            i_upper.and_then(|i| j_upper.and_then(|j| usize::checked_add(i, j))),
82        )
83    }
84}
85
86// Deprecated: According to the documentation for ExactSizeIterator,
87// "If an adapter makes an iterator longer, then it’s usually incorrect for
88// that adapter to implement ExactSizeIterator."
89
90// impl<I, J> iter::ExactSizeIterator for AlternatingAll<I, J>
91// where
92//     I: iter::ExactSizeIterator,
93//     J: iter::ExactSizeIterator<Item = I::Item>,
94// {
95//     fn len(&self) -> usize {
96//         self.i.len() + self.j.len()
97//     }
98// }
99impl<I, J> iter::FusedIterator for AlternatingAll<I, J>
100where
101    I: iter::FusedIterator,
102    J: iter::FusedIterator<Item = I::Item>,
103{
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn equal_lengths() {
112        let a = [1, 2, 3];
113        let b = [4, 5, 6];
114
115        let mut iter = a.iter().alternate_with_all(b.iter());
116
117        assert_eq!(iter.next(), Some(&1));
118        assert_eq!(iter.next(), Some(&4));
119        assert_eq!(iter.next(), Some(&2));
120        assert_eq!(iter.next(), Some(&5));
121        assert_eq!(iter.next(), Some(&3));
122        assert_eq!(iter.next(), Some(&6));
123        assert_eq!(iter.next(), None);
124    }
125
126    #[test]
127    fn different_lengths() {
128        let a = [1, 2, 3];
129        let b = [4, 5];
130
131        let mut iter = a.iter().alternate_with_all(b.iter());
132
133        assert_eq!(iter.next(), Some(&1));
134        assert_eq!(iter.next(), Some(&4));
135        assert_eq!(iter.next(), Some(&2));
136        assert_eq!(iter.next(), Some(&5));
137        assert_eq!(iter.next(), Some(&3));
138        assert_eq!(iter.next(), None);
139    }
140
141    #[test]
142    fn empty_iterators() {
143        let a: [i32; 0] = [];
144        let b: [i32; 0] = [];
145
146        let mut iter = a.iter().alternate_with_all(b.iter());
147
148        assert_eq!(iter.next(), None);
149    }
150
151    #[test]
152    fn one_empty_iterator() {
153        let a = [1, 2, 3];
154        let b: [i32; 0] = [];
155
156        let mut iter = a.iter().alternate_with_all(b.iter());
157
158        assert_eq!(iter.next(), Some(&1));
159        assert_eq!(iter.next(), Some(&2));
160        assert_eq!(iter.next(), Some(&3));
161        assert_eq!(iter.next(), None);
162    }
163
164    #[test]
165    fn same_iterator() {
166        let a = [1, 2, 3];
167
168        let mut iter = a.iter().alternate_with_all(a.iter());
169
170        assert_eq!(iter.next(), Some(&1));
171        assert_eq!(iter.next(), Some(&1));
172        assert_eq!(iter.next(), Some(&2));
173        assert_eq!(iter.next(), Some(&2));
174        assert_eq!(iter.next(), Some(&3));
175        assert_eq!(iter.next(), Some(&3));
176        assert_eq!(iter.next(), None);
177    }
178    #[test]
179    fn size_hint_accurate() {
180        let a = [1, 2, 3];
181        let b = [4, 5];
182
183        assert_eq!(
184            a.iter().size_hint().1,
185            Some(a.iter().count()),
186            "Sanity check failed"
187        );
188        assert_eq!(
189            b.iter().size_hint().1,
190            Some(b.iter().count()),
191            "Sanity check failed"
192        );
193
194        let iter = a.iter().alternate_with_all(b.iter());
195
196        assert_eq!(iter.size_hint().1, Some(iter.count()));
197    }
198
199    #[test]
200    fn size_hint() {
201        let a = [1, 2, 3];
202        let b = [4, 5];
203
204        assert_eq!(a.iter().size_hint(), (3, Some(3)), "Sanity check failed");
205        assert_eq!(b.iter().size_hint(), (2, Some(2)), "Sanity check failed");
206
207        let iter = a.iter().alternate_with_all(b.iter());
208
209        assert_eq!(iter.size_hint(), (5, Some(5)));
210        assert_eq!(iter.count(), 5, "Inaccurate size hint");
211    }
212    #[test]
213    fn size_hint_unbounded_right() {
214        let a = [1, 2, 3];
215        let b = iter::repeat(&0);
216
217        assert_eq!(a.iter().size_hint(), (3, Some(3)), "Sanity check failed");
218        assert_eq!(b.size_hint(), (usize::MAX, None), "Sanity check failed");
219
220        let iter = a.iter().alternate_with_all(b);
221
222        assert_eq!(iter.size_hint(), (usize::MAX, None));
223    }
224    #[test]
225    fn size_hint_unbounded_left() {
226        let a = iter::repeat(&0);
227        let b = [1, 2, 3];
228
229        assert_eq!(a.size_hint(), (usize::MAX, None), "Sanity check failed");
230        assert_eq!(b.iter().size_hint(), (3, Some(3)), "Sanity check failed");
231
232        let iter = a.alternate_with_all(b.iter());
233
234        assert_eq!(iter.size_hint(), (usize::MAX, None));
235    }
236    #[test]
237    fn size_hint_bound_exceed_max() {
238        let a = 0..usize::MAX;
239        let b = 0..3;
240
241        assert_eq!(
242            a.size_hint(),
243            (usize::MAX, Some(usize::MAX)),
244            "Sanity check failed"
245        );
246        assert_eq!(b.size_hint(), (3, Some(3)), "Sanity check failed");
247
248        let iter = a.alternate_with_all(b);
249
250        assert_eq!(iter.size_hint(), (usize::MAX, None));
251    }
252    #[test]
253    fn size_hint_bound_exactly_max() {
254        let a = 0..usize::MAX;
255        let b = 0..0;
256
257        assert_eq!(
258            a.size_hint(),
259            (usize::MAX, Some(usize::MAX)),
260            "Sanity check failed"
261        );
262        assert_eq!(b.size_hint(), (0, Some(0)), "Sanity check failed");
263
264        let iter = a.alternate_with_all(b);
265
266        assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX)));
267    }
268}