diff options
Diffstat (limited to 'compiler/rustc_data_structures/src/sso/either_iter.rs')
-rw-r--r-- | compiler/rustc_data_structures/src/sso/either_iter.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/compiler/rustc_data_structures/src/sso/either_iter.rs b/compiler/rustc_data_structures/src/sso/either_iter.rs new file mode 100644 index 000000000..131eeef45 --- /dev/null +++ b/compiler/rustc_data_structures/src/sso/either_iter.rs @@ -0,0 +1,75 @@ +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<L, R> { + Left(L), + Right(R), +} + +impl<L, R> Iterator for EitherIter<L, R> +where + L: Iterator, + R: Iterator<Item = L::Item>, +{ + type Item = L::Item; + + fn next(&mut self) -> Option<Self::Item> { + match self { + EitherIter::Left(l) => l.next(), + EitherIter::Right(r) => r.next(), + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + match self { + EitherIter::Left(l) => l.size_hint(), + EitherIter::Right(r) => r.size_hint(), + } + } +} + +impl<L, R> ExactSizeIterator for EitherIter<L, R> +where + L: ExactSizeIterator, + R: ExactSizeIterator, + EitherIter<L, R>: Iterator, +{ + fn len(&self) -> usize { + match self { + EitherIter::Left(l) => l.len(), + EitherIter::Right(r) => r.len(), + } + } +} + +impl<L, R> FusedIterator for EitherIter<L, R> +where + L: FusedIterator, + R: FusedIterator, + EitherIter<L, R>: Iterator, +{ +} + +impl<L, R> fmt::Debug for EitherIter<L, R> +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), + } + } +} |