1use std::cmp;
2use std::iter::IntoIterator;
3
4#[doc(hidden)]
5#[derive(Clone, Debug)]
6#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
7pub struct ZipOption<A, B> {
8 a: A,
9 b: B,
10 index: usize,
12 len: usize,
13}
14
15pub trait ZipOpt {
18 fn zip_option<U>(self, other: U) -> ZipOption<Self, U::IntoIter>
39 where Self: Sized, U: IntoIterator;
40}
41
42impl<I: Iterator> ZipOpt for I {
43 #[inline]
44 fn zip_option<U>(self, other: U) -> ZipOption<Self, U::IntoIter>
45 where Self: Sized, U: IntoIterator {
46
47 ZipOption::new(self, other.into_iter())
48 }
49}
50
51impl<A, B> Iterator for ZipOption<A, B> where A: Iterator, B: Iterator {
52 type Item = (Option<A::Item>, Option<B::Item>);
53
54 #[inline]
55 fn next(&mut self) -> Option<Self::Item> {
56 ZipImpl::next(self)
57 }
58
59 #[inline]
60 fn size_hint(&self) -> (usize, Option<usize>) {
61 ZipImpl::size_hint(self)
62 }
63
64 #[inline]
65 fn nth(&mut self, n: usize) -> Option<Self::Item> {
66 ZipImpl::nth(self, n)
67 }
68}
69
70#[doc(hidden)]
71impl<A, B> DoubleEndedIterator for ZipOption<A, B> where
72A: DoubleEndedIterator + ExactSizeIterator,
73B: DoubleEndedIterator + ExactSizeIterator,
74{
75 #[inline]
76 fn next_back(&mut self) -> Option<(Option<A::Item>, Option<B::Item>)> {
77 ZipImpl::next_back(self)
78 }
79}
80
81#[doc(hidden)]
82trait ZipImpl<A, B> {
83 type Item;
84 fn new(a: A, b: B) -> Self;
85 fn next(&mut self) -> Option<Self::Item>;
86 fn size_hint(&self) -> (usize, Option<usize>);
87 fn nth(&mut self, n: usize) -> Option<Self::Item>;
88 fn super_nth(&mut self, mut n: usize) -> Option<Self::Item> {
89 while let Some(x) = self.next() {
90 if n == 0 { return Some(x) }
91 n -= 1;
92 }
93 None
94 }
95 fn next_back(&mut self) -> Option<Self::Item>
96 where A: DoubleEndedIterator + ExactSizeIterator,
97 B: DoubleEndedIterator + ExactSizeIterator;
98}
99
100#[doc(hidden)]
101impl<A, B> ZipImpl<A, B> for ZipOption<A, B>
102 where A: Iterator, B: Iterator {
103 type Item = (Option<A::Item>, Option<B::Item>);
104 fn new(a: A, b: B) -> Self {
105 ZipOption {
106 a,
107 b,
108 index: 0, len: 0, }
111 }
112
113 #[inline]
114 fn next(&mut self) -> Option<(Option<A::Item>, Option<B::Item>)> {
115 let first = self.a.next();
116 let second = self.b.next();
117
118 if first.is_some() || second.is_some() {
119 Some((first, second))
120 } else {
121 None
122 }
123 }
124
125 #[inline]
126 fn nth(&mut self, n: usize) -> Option<Self::Item> {
127 self.super_nth(n)
128 }
129
130 #[inline]
131 fn next_back(&mut self) -> Option<(Option<A::Item>, Option<B::Item>)>
132 where A: DoubleEndedIterator + ExactSizeIterator,
133 B: DoubleEndedIterator + ExactSizeIterator {
134 let a_sz = self.a.len();
135 let b_sz = self.b.len();
136 if a_sz != b_sz {
137 if a_sz > b_sz {
139 for _ in 0..a_sz - b_sz { self.a.next_back(); }
140 } else {
141 for _ in 0..b_sz - a_sz { self.b.next_back(); }
142 }
143 }
144 match (self.a.next_back(), self.b.next_back()) {
145 (None, None) => None,
146 (f,s) => Some((f, s)),
147 }
148 }
149
150 #[inline]
151 fn size_hint(&self) -> (usize, Option<usize>) {
152 let (a_lower, a_upper) = self.a.size_hint();
153 let (b_lower, b_upper) = self.b.size_hint();
154
155 let lower = cmp::min(a_lower, b_lower);
156
157 let upper = match (a_upper, b_upper) {
158 (Some(x), Some(y)) => Some(cmp::max(x,y)),
159 (Some(x), None) => Some(x),
160 (None, Some(y)) => Some(y),
161 (None, None) => None
162 };
163
164 (lower, upper)
165 }
166}