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