1use core::iter::FusedIterator;
4
5use crate::EitherOrBoth;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ChainedIterEitherOrBoth<T>(EitherOrBoth<T, T>);
11
12#[derive(Debug, Clone, Default, PartialEq, Eq)]
14pub struct IntoIterEitherOrBoth<T>(Items<T>);
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18struct Items<T> {
19 inner: EitherOrBoth<Option<T>>,
20}
21
22#[derive(Debug, Clone, Default, PartialEq, Eq)]
24pub struct IterEitherOrBoth<'a, T>(Items<&'a T>);
25
26#[derive(Debug, Default, PartialEq, Eq)]
28pub struct IterMutEitherOrBoth<'a, T>(Items<&'a mut T>);
29
30#[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 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}