1 | use super::size_hint; |
2 | |
3 | /// An iterator which iterates two other iterators simultaneously |
4 | /// |
5 | /// See [`.zip_eq()`](crate::Itertools::zip_eq) for more information. |
6 | #[derive(Clone, Debug)] |
7 | #[must_use = "iterator adaptors are lazy and do nothing unless consumed" ] |
8 | pub struct ZipEq<I, J> { |
9 | a: I, |
10 | b: J, |
11 | } |
12 | |
13 | /// Iterate `i` and `j` in lock step. |
14 | /// |
15 | /// **Panics** if the iterators are not of the same length. |
16 | /// |
17 | /// [`IntoIterator`] enabled version of [`Itertools::zip_eq`](crate::Itertools::zip_eq). |
18 | /// |
19 | /// ``` |
20 | /// use itertools::zip_eq; |
21 | /// |
22 | /// let data = [1, 2, 3, 4, 5]; |
23 | /// for (a, b) in zip_eq(&data[..data.len() - 1], &data[1..]) { |
24 | /// /* loop body */ |
25 | /// } |
26 | /// ``` |
27 | pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter> |
28 | where I: IntoIterator, |
29 | J: IntoIterator |
30 | { |
31 | ZipEq { |
32 | a: i.into_iter(), |
33 | b: j.into_iter(), |
34 | } |
35 | } |
36 | |
37 | impl<I, J> Iterator for ZipEq<I, J> |
38 | where I: Iterator, |
39 | J: Iterator |
40 | { |
41 | type Item = (I::Item, J::Item); |
42 | |
43 | fn next(&mut self) -> Option<Self::Item> { |
44 | match (self.a.next(), self.b.next()) { |
45 | (None, None) => None, |
46 | (Some(a), Some(b)) => Some((a, b)), |
47 | (None, Some(_)) | (Some(_), None) => |
48 | panic!("itertools: .zip_eq() reached end of one iterator before the other" ) |
49 | } |
50 | } |
51 | |
52 | fn size_hint(&self) -> (usize, Option<usize>) { |
53 | size_hint::min(self.a.size_hint(), self.b.size_hint()) |
54 | } |
55 | } |
56 | |
57 | impl<I, J> ExactSizeIterator for ZipEq<I, J> |
58 | where I: ExactSizeIterator, |
59 | J: ExactSizeIterator |
60 | {} |
61 | |