// Copyright 2025 Jonas Kruckenberg // // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. use core::any::type_name; use core::cmp; pub trait IteratorExt { fn zip_eq(self, other: U) -> ZipEq::IntoIter> where Self: Sized, U: IntoIterator; } impl IteratorExt for I where I: Iterator, { fn zip_eq(self, other: U) -> ZipEq::IntoIter> where Self: Sized, U: IntoIterator, { ZipEq { a: self, b: other.into_iter(), } } } /// like Iterator::zip but panics if one iterator ends before /// the other. The `param_predicate` is required to select exactly as many /// elements of `params` as there are elements in `arguments`. pub struct ZipEq { a: A, b: B, } impl Iterator for ZipEq where A: Iterator, B: Iterator, { type Item = (A::Item, B::Item); fn next(&mut self) -> Option { match (self.a.next(), self.b.next()) { (Some(a), Some(b)) => Some((a, b)), (None, None) => None, (None, _) => panic!( "iterators had different lengths. {} was shorter than {}", type_name::(), type_name::() ), (_, None) => panic!( "iterators had different lengths. {} was shorter than {}", type_name::(), type_name::() ), } } fn size_hint(&self) -> (usize, Option) { let (a_min, a_max) = self.a.size_hint(); let (b_min, b_max) = self.a.size_hint(); ( cmp::min(a_min, b_min), a_max .and_then(|a| Some((a, b_max?))) .map(|(a, b)| cmp::min(a, b)), ) } } impl ExactSizeIterator for ZipEq where A: ExactSizeIterator, B: ExactSizeIterator, { fn len(&self) -> usize { debug_assert_eq!(self.a.len(), self.b.len()); self.a.len() } }