p3_util/
zip_eq.rs

1/// An iterator which iterates two other iterators of the same length simultaneously.
2///
3/// Equality of the lengths of `a` and `b` are checked at construction time.
4#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
5pub struct ZipEq<A, B> {
6    a: A,
7    b: B,
8}
9
10/// Zips two iterators but **panics** if they are not of the same length.
11///
12/// Similar to `itertools::zip_eq`, but we check the lengths at construction time.
13pub fn zip_eq<A, AIter, B, BIter, Error>(
14    a: A,
15    b: B,
16    err: Error,
17) -> Result<ZipEq<A::IntoIter, B::IntoIter>, Error>
18where
19    A: IntoIterator<IntoIter = AIter>,
20    AIter: ExactSizeIterator,
21    B: IntoIterator<IntoIter = BIter>,
22    BIter: ExactSizeIterator,
23{
24    let a_iter = a.into_iter();
25    let b_iter = b.into_iter();
26    match a_iter.len() == b_iter.len() {
27        true => Ok(ZipEq {
28            a: a_iter,
29            b: b_iter,
30        }),
31        false => Err(err),
32    }
33}
34
35impl<A, B> Iterator for ZipEq<A, B>
36where
37    A: ExactSizeIterator, // We need to use ExactSizeIterator here otherwise the size_hint() methods could differ.
38    B: ExactSizeIterator,
39{
40    type Item = (A::Item, B::Item);
41
42    fn next(&mut self) -> Option<Self::Item> {
43        match (self.a.next(), self.b.next()) {
44            (Some(a), Some(b)) => Some((a, b)),
45            (None, None) => None,
46            _ => unreachable!("The iterators must have the same length."),
47        }
48    }
49
50    fn size_hint(&self) -> (usize, Option<usize>) {
51        // self.a.size_hint() = self.b.size_hint() as a and b are ExactSizeIterators
52        // and we checked that they are the same length at construction time.
53        debug_assert_eq!(self.a.size_hint(), self.b.size_hint());
54        self.a.size_hint()
55    }
56}
57
58impl<A, B> ExactSizeIterator for ZipEq<A, B>
59where
60    A: ExactSizeIterator,
61    B: ExactSizeIterator,
62{
63}