2 use super::super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen};
4 /// An iterator that iterates two other iterators simultaneously.
6 /// This `struct` is created by the [`zip`] method on [`Iterator`]. See its
7 /// documentation for more.
9 /// [`zip`]: trait.Iterator.html#method.zip
10 /// [`Iterator`]: trait.Iterator.html
11 #[derive(Clone, Debug)]
12 #[must_use = "iterators are lazy and do nothing unless consumed"]
13 #[stable(feature = "rust1", since = "1.0.0")]
14 pub struct Zip<A, B> {
17 // index and len are only used by the specialized version of zip
22 #[stable(feature = "rust1", since = "1.0.0")]
23 impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
25 type Item = (A::Item, B::Item);
28 fn next(&mut self) -> Option<Self::Item> {
33 fn size_hint(&self) -> (usize, Option<usize>) {
34 ZipImpl::size_hint(self)
38 fn nth(&mut self, n: usize) -> Option<Self::Item> {
43 #[stable(feature = "rust1", since = "1.0.0")]
44 impl<A, B> DoubleEndedIterator for Zip<A, B> where
45 A: DoubleEndedIterator + ExactSizeIterator,
46 B: DoubleEndedIterator + ExactSizeIterator,
49 fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
50 ZipImpl::next_back(self)
54 // Zip specialization trait
56 pub(in super::super) trait ZipImpl<A, B> {
58 fn new(a: A, b: B) -> Self;
59 fn next(&mut self) -> Option<Self::Item>;
60 fn size_hint(&self) -> (usize, Option<usize>);
61 fn nth(&mut self, n: usize) -> Option<Self::Item>;
62 fn super_nth(&mut self, mut n: usize) -> Option<Self::Item> {
63 while let Some(x) = self.next() {
64 if n == 0 { return Some(x) }
69 fn next_back(&mut self) -> Option<Self::Item>
70 where A: DoubleEndedIterator + ExactSizeIterator,
71 B: DoubleEndedIterator + ExactSizeIterator;
76 impl<A, B> ZipImpl<A, B> for Zip<A, B>
77 where A: Iterator, B: Iterator
79 type Item = (A::Item, B::Item);
80 default fn new(a: A, b: B) -> Self {
90 default fn next(&mut self) -> Option<(A::Item, B::Item)> {
91 self.a.next().and_then(|x| {
92 self.b.next().and_then(|y| {
99 default fn nth(&mut self, n: usize) -> Option<Self::Item> {
104 default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
105 where A: DoubleEndedIterator + ExactSizeIterator,
106 B: DoubleEndedIterator + ExactSizeIterator
108 let a_sz = self.a.len();
109 let b_sz = self.b.len();
111 // Adjust a, b to equal length
113 for _ in 0..a_sz - b_sz { self.a.next_back(); }
115 for _ in 0..b_sz - a_sz { self.b.next_back(); }
118 match (self.a.next_back(), self.b.next_back()) {
119 (Some(x), Some(y)) => Some((x, y)),
120 (None, None) => None,
126 default fn size_hint(&self) -> (usize, Option<usize>) {
127 let (a_lower, a_upper) = self.a.size_hint();
128 let (b_lower, b_upper) = self.b.size_hint();
130 let lower = cmp::min(a_lower, b_lower);
132 let upper = match (a_upper, b_upper) {
133 (Some(x), Some(y)) => Some(cmp::min(x,y)),
134 (Some(x), None) => Some(x),
135 (None, Some(y)) => Some(y),
144 impl<A, B> ZipImpl<A, B> for Zip<A, B>
145 where A: TrustedRandomAccess, B: TrustedRandomAccess
147 fn new(a: A, b: B) -> Self {
148 let len = cmp::min(a.len(), b.len());
158 fn next(&mut self) -> Option<(A::Item, B::Item)> {
159 if self.index < self.len {
163 Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
165 } else if A::may_have_side_effect() && self.index < self.a.len() {
166 // match the base implementation's potential side effects
168 self.a.get_unchecked(self.index);
178 fn size_hint(&self) -> (usize, Option<usize>) {
179 let len = self.len - self.index;
184 fn nth(&mut self, n: usize) -> Option<Self::Item> {
185 let delta = cmp::min(n, self.len - self.index);
186 let end = self.index + delta;
187 while self.index < end {
190 if A::may_have_side_effect() {
191 unsafe { self.a.get_unchecked(i); }
193 if B::may_have_side_effect() {
194 unsafe { self.b.get_unchecked(i); }
198 self.super_nth(n - delta)
202 fn next_back(&mut self) -> Option<(A::Item, B::Item)>
203 where A: DoubleEndedIterator + ExactSizeIterator,
204 B: DoubleEndedIterator + ExactSizeIterator
206 // Adjust a, b to equal length
207 if A::may_have_side_effect() {
208 let sz = self.a.len();
210 for _ in 0..sz - cmp::max(self.len, self.index) {
215 if B::may_have_side_effect() {
216 let sz = self.b.len();
218 for _ in 0..sz - self.len {
223 if self.index < self.len {
227 Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
235 #[stable(feature = "rust1", since = "1.0.0")]
236 impl<A, B> ExactSizeIterator for Zip<A, B>
237 where A: ExactSizeIterator, B: ExactSizeIterator {}
240 unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
241 where A: TrustedRandomAccess,
242 B: TrustedRandomAccess,
244 unsafe fn get_unchecked(&mut self, i: usize) -> (A::Item, B::Item) {
245 (self.a.get_unchecked(i), self.b.get_unchecked(i))
248 fn may_have_side_effect() -> bool {
249 A::may_have_side_effect() || B::may_have_side_effect()
253 #[stable(feature = "fused", since = "1.26.0")]
254 impl<A, B> FusedIterator for Zip<A, B>
255 where A: FusedIterator, B: FusedIterator, {}
257 #[unstable(feature = "trusted_len", issue = "37572")]
258 unsafe impl<A, B> TrustedLen for Zip<A, B>
259 where A: TrustedLen, B: TrustedLen,
262 /// An iterator whose items are random-accessible efficiently
266 /// The iterator's .len() and size_hint() must be exact.
267 /// `.len()` must be cheap to call.
269 /// .get_unchecked() must return distinct mutable references for distinct
270 /// indices (if applicable), and must return a valid reference if index is in
272 pub(crate) unsafe trait TrustedRandomAccess : ExactSizeIterator {
273 unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
274 /// Returns `true` if getting an iterator element may have
275 /// side effects. Remember to take inner iterators into account.
276 fn may_have_side_effect() -> bool;