use std::fmt; use std::iter::ExactSizeIterator; use std::iter::FusedIterator; use std::iter::Iterator; /// Iterator which may contain instance of /// one of two specific implementations. /// /// Note: For most methods providing custom /// implementation may marginally /// improve performance by avoiding /// doing Left/Right match on every step /// and doing it only once instead. #[derive(Clone)] pub enum EitherIter { Left(L), Right(R), } impl Iterator for EitherIter where L: Iterator, R: Iterator, { type Item = L::Item; fn next(&mut self) -> Option { match self { EitherIter::Left(l) => l.next(), EitherIter::Right(r) => r.next(), } } fn size_hint(&self) -> (usize, Option) { match self { EitherIter::Left(l) => l.size_hint(), EitherIter::Right(r) => r.size_hint(), } } } impl ExactSizeIterator for EitherIter where L: ExactSizeIterator, R: ExactSizeIterator, EitherIter: Iterator, { fn len(&self) -> usize { match self { EitherIter::Left(l) => l.len(), EitherIter::Right(r) => r.len(), } } } impl FusedIterator for EitherIter where L: FusedIterator, R: FusedIterator, EitherIter: Iterator, { } impl fmt::Debug for EitherIter where L: fmt::Debug, R: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { EitherIter::Left(l) => l.fmt(f), EitherIter::Right(r) => r.fmt(f), } } }