either_or_both/either/
iter.rs

1//! Iterators for [`Either`]
2
3use core::iter::FusedIterator;
4
5use crate::Either;
6
7/// An iterator over the contained value of a uniform type
8#[derive(Debug, Clone, Default, PartialEq, Eq)]
9pub struct IntoIterEither<T>(Item<T>);
10
11/// The `Item` used to iterate over an `Either`
12#[derive(Debug, Clone, PartialEq, Eq)]
13struct Item<T>(Option<Either<T>>);
14
15/// An iterator over the references to the contained values of a uniform type
16#[derive(Debug, Clone, Default, PartialEq, Eq)]
17pub struct IterEither<'a, T>(Item<&'a T>);
18
19/// An iterator over the mutable references to the contained values of a uniform type
20#[derive(Debug, Default, PartialEq, Eq)]
21pub struct IterMutEither<'a, T>(Item<&'a mut T>);
22
23/// An iterator over the contained iterator of a uniform type
24#[derive(Debug, Clone)]
25pub struct InnerIterEither<T>(Either<T>);
26
27/// An iterator over `Eithers`
28#[derive(Debug, Clone)]
29pub struct SwapIterEither<L, R>(Either<L, R>);
30
31impl<T> InnerIterEither<T> {
32    pub(crate) const fn new(either: Either<T, T>) -> Self {
33        Self(either)
34    }
35}
36
37impl<T> DoubleEndedIterator for InnerIterEither<T>
38where
39    T: DoubleEndedIterator,
40{
41    #[inline]
42    fn next_back(&mut self) -> Option<Self::Item> {
43        self.0.as_mut().reduce_map(DoubleEndedIterator::next_back)
44    }
45}
46
47impl<T> ExactSizeIterator for InnerIterEither<T> where T: ExactSizeIterator {}
48
49impl<T> FusedIterator for InnerIterEither<T> where T: FusedIterator {}
50
51impl<T> Iterator for InnerIterEither<T>
52where
53    T: Iterator,
54{
55    type Item = T::Item;
56
57    #[inline]
58    fn next(&mut self) -> Option<Self::Item> {
59        self.0.as_mut().reduce_map(Iterator::next)
60    }
61
62    #[inline]
63    fn size_hint(&self) -> (usize, Option<usize>) {
64        self.0.as_ref().reduce_map(Iterator::size_hint)
65    }
66}
67
68impl<T> IntoIterEither<T> {
69    pub(crate) fn new(either: Either<T>) -> Self {
70        Self(either.into())
71    }
72}
73
74impl<T> DoubleEndedIterator for IntoIterEither<T> {
75    #[inline]
76    fn next_back(&mut self) -> Option<Self::Item> {
77        self.0.next_back()
78    }
79}
80
81impl<T> ExactSizeIterator for IntoIterEither<T> {}
82impl<T> FusedIterator for IntoIterEither<T> {}
83
84impl<T> Iterator for IntoIterEither<T> {
85    type Item = T;
86
87    #[inline]
88    fn next(&mut self) -> Option<Self::Item> {
89        self.0.next()
90    }
91
92    #[inline]
93    fn size_hint(&self) -> (usize, Option<usize>) {
94        self.0.size_hint()
95    }
96}
97
98impl<T> From<Either<T>> for Item<T> {
99    fn from(value: Either<T>) -> Self {
100        Self(Some(value))
101    }
102}
103
104impl<T> Default for Item<T> {
105    fn default() -> Self {
106        Self(None)
107    }
108}
109
110impl<T> DoubleEndedIterator for Item<T> {
111    #[inline]
112    fn next_back(&mut self) -> Option<Self::Item> {
113        self.next()
114    }
115}
116
117impl<T> ExactSizeIterator for Item<T> {}
118impl<T> FusedIterator for Item<T> {}
119
120impl<T> Iterator for Item<T> {
121    type Item = T;
122
123    #[inline]
124    fn next(&mut self) -> Option<Self::Item> {
125        self.0.take().map(Either::reduce)
126    }
127
128    fn size_hint(&self) -> (usize, Option<usize>) {
129        match &self.0 {
130            Some(_) => (1, Some(1)),
131            None => (0, Some(0)),
132        }
133    }
134}
135
136impl<'a, T> IterEither<'a, T> {
137    pub(crate) fn new(either: &'a Either<T>) -> Self {
138        Self(either.as_ref().into())
139    }
140}
141
142impl<T> DoubleEndedIterator for IterEither<'_, T> {
143    #[inline]
144    fn next_back(&mut self) -> Option<Self::Item> {
145        self.0.next_back()
146    }
147}
148
149impl<T> ExactSizeIterator for IterEither<'_, T> {}
150impl<T> FusedIterator for IterEither<'_, T> {}
151
152impl<'a, T> Iterator for IterEither<'a, T> {
153    type Item = &'a T;
154
155    #[inline]
156    fn next(&mut self) -> Option<Self::Item> {
157        self.0.next()
158    }
159
160    #[inline]
161    fn size_hint(&self) -> (usize, Option<usize>) {
162        self.0.size_hint()
163    }
164}
165
166impl<'a, T> IterMutEither<'a, T> {
167    pub(crate) fn new(either: &'a mut Either<T>) -> Self {
168        Self(either.as_mut().into())
169    }
170}
171
172impl<T> DoubleEndedIterator for IterMutEither<'_, T> {
173    #[inline]
174    fn next_back(&mut self) -> Option<Self::Item> {
175        self.0.next_back()
176    }
177}
178
179impl<T> ExactSizeIterator for IterMutEither<'_, T> {}
180impl<T> FusedIterator for IterMutEither<'_, T> {}
181
182impl<'a, T> Iterator for IterMutEither<'a, T> {
183    type Item = &'a mut T;
184
185    #[inline]
186    fn next(&mut self) -> Option<Self::Item> {
187        self.0.next()
188    }
189
190    #[inline]
191    fn size_hint(&self) -> (usize, Option<usize>) {
192        self.0.size_hint()
193    }
194}
195
196impl<L, R> SwapIterEither<L, R> {
197    pub(crate) const fn new(either: Either<L, R>) -> Self {
198        Self(either)
199    }
200}
201
202impl<L, R> DoubleEndedIterator for SwapIterEither<L, R>
203where
204    L: DoubleEndedIterator,
205    R: DoubleEndedIterator,
206{
207    #[inline]
208    fn next_back(&mut self) -> Option<Self::Item> {
209        match self.0.as_mut() {
210            Either::Left(left) => left.next_back().map(Either::Left),
211            Either::Right(right) => right.next_back().map(Either::Right),
212        }
213    }
214}
215
216impl<L, R> ExactSizeIterator for SwapIterEither<L, R>
217where
218    L: ExactSizeIterator,
219    R: ExactSizeIterator,
220{
221}
222
223impl<L, R> FusedIterator for SwapIterEither<L, R>
224where
225    L: FusedIterator,
226    R: FusedIterator,
227{
228}
229
230impl<L, R> Iterator for SwapIterEither<L, R>
231where
232    L: Iterator,
233    R: Iterator,
234{
235    type Item = Either<L::Item, R::Item>;
236
237    #[inline]
238    fn next(&mut self) -> Option<Self::Item> {
239        match self.0.as_mut() {
240            Either::Left(left) => left.next().map(Either::Left),
241            Either::Right(right) => right.next().map(Either::Right),
242        }
243    }
244
245    fn size_hint(&self) -> (usize, Option<usize>) {
246        self.0
247            .as_ref()
248            .bireduce(Iterator::size_hint, Iterator::size_hint)
249    }
250}
251
252#[cfg(test)]
253mod tests {
254    use super::*;
255
256    #[test]
257    fn item_default() {
258        assert_eq!(Item::default(), Item::<u8>(None));
259    }
260}