Skip to main content

polars_utils/itertools/
zip_eq.rs

1use std::cmp;
2
3/// An iterator which iterates two other iterators simultaneously
4/// and panic if they have different lengths.
5#[derive(Clone, Debug)]
6#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
7pub struct ZipEq<I, J> {
8    a: I,
9    b: J,
10}
11
12impl<I: Iterator, J: Iterator> Iterator for ZipEq<I, J> {
13    type Item = (I::Item, J::Item);
14
15    fn next(&mut self) -> Option<Self::Item> {
16        match (self.a.next(), self.b.next()) {
17            (None, None) => None,
18            (Some(a), Some(b)) => Some((a, b)),
19            (None, Some(_)) | (Some(_), None) => {
20                panic!("itertools: .zip_eq() reached end of one iterator before the other")
21            },
22        }
23    }
24
25    fn size_hint(&self) -> (usize, Option<usize>) {
26        let (a_lower, a_upper) = self.a.size_hint();
27        let (b_lower, b_upper) = self.b.size_hint();
28        let lower = cmp::min(a_lower, b_lower);
29        let upper = match (a_upper, b_upper) {
30            (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
31            _ => a_upper.or(b_upper),
32        };
33        (lower, upper)
34    }
35}
36
37impl<I: ExactSizeIterator, J: ExactSizeIterator> ExactSizeIterator for ZipEq<I, J> {}
38
39/// Zips two iterators but **panics** if they are not of the same length.
40pub fn zip_eq<I, J>(i: I, j: J) -> ZipEq<I::IntoIter, J::IntoIter>
41where
42    I: IntoIterator,
43    J: IntoIterator,
44{
45    ZipEq {
46        a: i.into_iter(),
47        b: j.into_iter(),
48    }
49}