macro_rules! impl_cons_iter( ($_A:ident, $_B:ident, ) => (); // stop ($A:ident, $($B:ident,)*) => ( impl_cons_iter!($($B,)*); #[allow(non_snake_case)] impl Iterator for ConsTuples where Iter: Iterator, { type Item = ($($B,)* X, ); fn next(&mut self) -> Option { self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } fn fold(self, accum: Acc, mut f: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, ))) } } #[allow(non_snake_case)] impl DoubleEndedIterator for ConsTuples where Iter: DoubleEndedIterator, { fn next_back(&mut self) -> Option { self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, )) } } ); ); impl_cons_iter!(A, B, C, D, E, F, G, H, I, J, K, L,); /// An iterator that maps an iterator of tuples like /// `((A, B), C)` to an iterator of `(A, B, C)`. /// /// Used by the `iproduct!()` macro. #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Debug)] pub struct ConsTuples where I: Iterator, { iter: I, } impl Clone for ConsTuples where I: Clone + Iterator, { clone_fields!(iter); } /// Create an iterator that maps for example iterators of /// `((A, B), C)` to `(A, B, C)`. pub fn cons_tuples(iterable: I) -> ConsTuples where I: IntoIterator { ConsTuples { iter: iterable.into_iter() } }