Skip to main content

either_or_both/either_or_both/
iter.rs

1//! Iterators for [`EitherOrBoth`]
2
3use core::iter::FusedIterator;
4
5use crate::EitherOrBoth;
6
7/// A iterator over the contained iterators of a uniform type chaining both iterators from
8/// left to right
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ChainedIterEitherOrBoth<T>(EitherOrBoth<T, T>);
11
12/// An iterator over the contained values of a uniform type
13#[derive(Debug, Clone, Default, PartialEq, Eq)]
14pub struct IntoIterEitherOrBoth<T>(Items<T>);
15
16/// The `Items` used to iterate over an `EitherOrBoth`
17#[derive(Debug, Clone, PartialEq, Eq)]
18struct Items<T> {
19    inner: EitherOrBoth<Option<T>>,
20}
21
22/// An iterator over the references to the contained values of a uniform type
23#[derive(Debug, Clone, Default, PartialEq, Eq)]
24pub struct IterEitherOrBoth<'a, T>(Items<&'a T>);
25
26/// An iterator over the mutable references to the contained values of a uniform type
27#[derive(Debug, Default, PartialEq, Eq)]
28pub struct IterMutEitherOrBoth<'a, T>(Items<&'a mut T>);
29
30/// An iterator over `EitherOrBoths`
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct SwapIterEitherOrBoth<L, R>(EitherOrBoth<L, R>);
33
34impl<T> ChainedIterEitherOrBoth<T> {
35    #[inline]
36    pub(crate) const fn new(either_or_both: EitherOrBoth<T, T>) -> Self {
37        Self(either_or_both)
38    }
39}
40
41impl<T> Default for ChainedIterEitherOrBoth<T>
42where
43    T: Default,
44{
45    #[inline]
46    fn default() -> Self {
47        Self(EitherOrBoth::Left(T::default()))
48    }
49}
50
51impl<T> DoubleEndedIterator for ChainedIterEitherOrBoth<T>
52where
53    T: DoubleEndedIterator,
54{
55    #[inline]
56    fn next_back(&mut self) -> Option<Self::Item> {
57        match self.0.as_mut() {
58            EitherOrBoth::Both(left, right) => right.next_back().or_else(|| left.next_back()),
59            EitherOrBoth::Left(side) | EitherOrBoth::Right(side) => side.next_back(),
60        }
61    }
62}
63
64impl<T> FusedIterator for ChainedIterEitherOrBoth<T> where T: FusedIterator {}
65
66impl<T> Iterator for ChainedIterEitherOrBoth<T>
67where
68    T: Iterator,
69{
70    type Item = T::Item;
71
72    #[inline]
73    fn next(&mut self) -> Option<Self::Item> {
74        match self.0.as_mut() {
75            EitherOrBoth::Both(left, right) => left.next().or_else(|| right.next()),
76            EitherOrBoth::Left(iter) | EitherOrBoth::Right(iter) => iter.next(),
77        }
78    }
79
80    fn size_hint(&self) -> (usize, Option<usize>) {
81        self.0
82            .as_ref()
83            .map(Iterator::size_hint)
84            .reduce(|(l_lower, l_upper), (r_lower, r_upper)| {
85                (
86                    l_lower.saturating_add(r_lower),
87                    l_upper.and_then(|l| r_upper.and_then(|r| l.checked_add(r))),
88                )
89            })
90    }
91}
92
93impl<T> IntoIterEitherOrBoth<T> {
94    #[inline]
95    pub(crate) fn new(either_or_both: EitherOrBoth<T, T>) -> Self {
96        Self(either_or_both.into())
97    }
98}
99
100impl<T> DoubleEndedIterator for IntoIterEitherOrBoth<T> {
101    #[inline]
102    fn next_back(&mut self) -> Option<Self::Item> {
103        self.0.next_back()
104    }
105}
106
107impl<T> ExactSizeIterator for IntoIterEitherOrBoth<T> {}
108impl<T> FusedIterator for IntoIterEitherOrBoth<T> {}
109
110impl<T> Iterator for IntoIterEitherOrBoth<T> {
111    type Item = T;
112
113    #[inline]
114    fn next(&mut self) -> Option<Self::Item> {
115        self.0.next()
116    }
117
118    #[inline]
119    fn size_hint(&self) -> (usize, Option<usize>) {
120        self.0.size_hint()
121    }
122}
123
124impl<T> From<EitherOrBoth<T>> for Items<T> {
125    #[inline]
126    fn from(value: EitherOrBoth<T>) -> Self {
127        Self {
128            inner: value.map(Some),
129        }
130    }
131}
132
133impl<T> Default for Items<T> {
134    #[inline]
135    fn default() -> Self {
136        Self {
137            inner: EitherOrBoth::Left(None),
138        }
139    }
140}
141
142impl<T> DoubleEndedIterator for Items<T> {
143    #[inline]
144    fn next_back(&mut self) -> Option<Self::Item> {
145        match self.inner.as_mut() {
146            EitherOrBoth::Both(_, right) | EitherOrBoth::Right(right) if right.is_some() => {
147                right.take()
148            }
149            EitherOrBoth::Both(left, None) | EitherOrBoth::Left(left) if left.is_some() => {
150                left.take()
151            }
152            _ => None,
153        }
154    }
155}
156
157impl<T> ExactSizeIterator for Items<T> {}
158impl<T> FusedIterator for Items<T> {}
159
160impl<T> Iterator for Items<T> {
161    type Item = T;
162
163    #[inline]
164    fn next(&mut self) -> Option<Self::Item> {
165        match self.inner.as_mut() {
166            EitherOrBoth::Both(left, _) | EitherOrBoth::Left(left) if left.is_some() => left.take(),
167            EitherOrBoth::Both(None, right) | EitherOrBoth::Right(right) if right.is_some() => {
168                right.take()
169            }
170            _ => None,
171        }
172    }
173
174    fn size_hint(&self) -> (usize, Option<usize>) {
175        match &self.inner {
176            EitherOrBoth::Both(Some(_), Some(_)) => (2, Some(2)),
177            EitherOrBoth::Left(Some(_))
178            | EitherOrBoth::Right(Some(_))
179            | EitherOrBoth::Both(None, Some(_))
180            | EitherOrBoth::Both(Some(_), None) => (1, Some(1)),
181            _ => (0, Some(0)),
182        }
183    }
184}
185
186impl<'a, T> IterEitherOrBoth<'a, T> {
187    #[inline]
188    pub(crate) fn new(either_or_both: &'a EitherOrBoth<T>) -> Self {
189        Self(either_or_both.as_ref().into())
190    }
191}
192
193impl<T> DoubleEndedIterator for IterEitherOrBoth<'_, T> {
194    #[inline]
195    fn next_back(&mut self) -> Option<Self::Item> {
196        self.0.next_back()
197    }
198}
199
200impl<T> ExactSizeIterator for IterEitherOrBoth<'_, T> {}
201impl<T> FusedIterator for IterEitherOrBoth<'_, T> {}
202
203impl<'a, T> Iterator for IterEitherOrBoth<'a, T> {
204    type Item = &'a T;
205
206    #[inline]
207    fn next(&mut self) -> Option<Self::Item> {
208        self.0.next()
209    }
210
211    #[inline]
212    fn size_hint(&self) -> (usize, Option<usize>) {
213        self.0.size_hint()
214    }
215}
216
217impl<'a, T> IterMutEitherOrBoth<'a, T> {
218    #[inline]
219    pub(crate) fn new(either_or_both: &'a mut EitherOrBoth<T>) -> Self {
220        Self(either_or_both.as_mut().into())
221    }
222}
223
224impl<T> DoubleEndedIterator for IterMutEitherOrBoth<'_, T> {
225    #[inline]
226    fn next_back(&mut self) -> Option<Self::Item> {
227        self.0.next_back()
228    }
229}
230
231impl<T> ExactSizeIterator for IterMutEitherOrBoth<'_, T> {}
232impl<T> FusedIterator for IterMutEitherOrBoth<'_, T> {}
233
234impl<'a, T> Iterator for IterMutEitherOrBoth<'a, T> {
235    type Item = &'a mut T;
236
237    #[inline]
238    fn next(&mut self) -> Option<Self::Item> {
239        self.0.next()
240    }
241
242    #[inline]
243    fn size_hint(&self) -> (usize, Option<usize>) {
244        self.0.size_hint()
245    }
246}
247
248impl<L, R> SwapIterEitherOrBoth<L, R> {
249    #[inline]
250    pub(crate) const fn new(either_or_both: EitherOrBoth<L, R>) -> Self {
251        Self(either_or_both)
252    }
253}
254
255impl<L, R> DoubleEndedIterator for SwapIterEitherOrBoth<L, R>
256where
257    L: DoubleEndedIterator,
258    R: DoubleEndedIterator,
259{
260    #[inline]
261    fn next_back(&mut self) -> Option<Self::Item> {
262        match self.0.as_mut() {
263            EitherOrBoth::Both(left, right) => (left.next_back(), right.next_back()).try_into().ok(),
264            EitherOrBoth::Left(left) => left.next_back().map(EitherOrBoth::Left),
265            EitherOrBoth::Right(right) => right.next_back().map(EitherOrBoth::Right),
266        }
267    }
268}
269
270impl<L, R> ExactSizeIterator for SwapIterEitherOrBoth<L, R>
271where
272    L: ExactSizeIterator,
273    R: ExactSizeIterator,
274{
275}
276
277impl<L, R> FusedIterator for SwapIterEitherOrBoth<L, R>
278where
279    L: FusedIterator,
280    R: FusedIterator,
281{
282}
283
284impl<L, R> Iterator for SwapIterEitherOrBoth<L, R>
285where
286    L: Iterator,
287    R: Iterator,
288{
289    type Item = EitherOrBoth<L::Item, R::Item>;
290
291    #[inline]
292    fn next(&mut self) -> Option<Self::Item> {
293        match self.0.as_mut() {
294            EitherOrBoth::Both(left, right) => (left.next(), right.next()).try_into().ok(),
295            EitherOrBoth::Left(left) => left.next().map(EitherOrBoth::Left),
296            EitherOrBoth::Right(right) => right.next().map(EitherOrBoth::Right),
297        }
298    }
299
300    fn size_hint(&self) -> (usize, Option<usize>) {
301        self.0
302            .as_ref()
303            .bimap(Iterator::size_hint, Iterator::size_hint)
304            .reduce(|(l_lower, l_upper), (r_lower, r_upper)| {
305                (
306                    l_lower.max(r_lower),
307                    // is `None` if the left or right upper bound is `None`
308                    l_upper.and_then(|l| r_upper.map(|r| l.max(r))),
309                )
310            })
311    }
312}
313
314#[cfg(test)]
315mod tests {
316    use rstest::rstest;
317    use EitherOrBoth::*;
318
319    use super::*;
320
321    #[rstest]
322    #[case::both(Both(1, 2), [Some(1), Some(2), None])]
323    #[case::left(Left(1), [Some(1), None, None])]
324    #[case::right(Right(2), [Some(2), None, None])]
325    fn items_next(#[case] either_or_both: EitherOrBoth<i32>, #[case] expected: [Option<i32>; 3]) {
326        let mut expected_iter = expected.into_iter();
327        let mut items = Items::from(either_or_both);
328        assert_eq!(items.next(), expected_iter.next().unwrap());
329        assert_eq!(items.next(), expected_iter.next().unwrap());
330        assert_eq!(items.next(), expected_iter.next().unwrap());
331    }
332
333    #[rstest]
334    #[case::both(Both(1, 2), [Some(2), Some(1), None])]
335    #[case::left(Left(1), [Some(1), None, None])]
336    #[case::right(Right(2), [Some(2), None, None])]
337    fn items_next_back(
338        #[case] either_or_both: EitherOrBoth<i32>,
339        #[case] expected: [Option<i32>; 3],
340    ) {
341        let mut expected_iter = expected.into_iter();
342        let mut items = Items::from(either_or_both);
343        assert_eq!(items.next_back(), expected_iter.next().unwrap());
344        assert_eq!(items.next_back(), expected_iter.next().unwrap());
345        assert_eq!(items.next_back(), expected_iter.next().unwrap());
346    }
347
348    #[rstest]
349    #[case::both(Both(1, 2), [(2, Some(2)), (1, Some(1)), (0, Some(0))])]
350    #[case::left(Left(1), [(1, Some(1)), (0, Some(0)), (0, Some(0))])]
351    #[case::right(Right(2), [(1, Some(1)), (0, Some(0)), (0, Some(0))])]
352    fn items_size_hint(
353        #[case] either_or_both: EitherOrBoth<i32>,
354        #[case] expected: [(usize, Option<usize>); 3],
355    ) {
356        let mut expected_iter = expected.into_iter();
357        let mut iter = Items::from(either_or_both);
358        assert_eq!(iter.size_hint(), expected_iter.next().unwrap());
359        iter.next();
360        assert_eq!(iter.size_hint(), expected_iter.next().unwrap());
361        iter.next();
362        assert_eq!(iter.size_hint(), expected_iter.next().unwrap());
363    }
364
365    #[test]
366    fn items_default() {
367        assert_eq!(Items { inner: Left(None) }, Items::<i32>::default());
368    }
369
370    #[test]
371    fn chained_iter_default() {
372        assert_eq!(
373            ChainedIterEitherOrBoth(Left('\0')),
374            ChainedIterEitherOrBoth::<char>::default()
375        );
376    }
377}