diff options
Diffstat (limited to 'third_party/rust/itertools/src/exactly_one_err.rs')
-rw-r--r-- | third_party/rust/itertools/src/exactly_one_err.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/third_party/rust/itertools/src/exactly_one_err.rs b/third_party/rust/itertools/src/exactly_one_err.rs new file mode 100644 index 0000000000..e4925ffb70 --- /dev/null +++ b/third_party/rust/itertools/src/exactly_one_err.rs @@ -0,0 +1,58 @@ +use std::iter::ExactSizeIterator; + +use crate::size_hint; + +/// Iterator returned for the error case of `IterTools::exactly_one()` +/// This iterator yields exactly the same elements as the input iterator. +/// +/// During the execution of exactly_one the iterator must be mutated. This wrapper +/// effectively "restores" the state of the input iterator when it's handed back. +/// +/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not +/// use a `Vec`. +#[derive(Debug, Clone)] +pub struct ExactlyOneError<I> +where + I: Iterator, +{ + first_two: (Option<I::Item>, Option<I::Item>), + inner: I, +} + +impl<I> ExactlyOneError<I> +where + I: Iterator, +{ + /// Creates a new `ExactlyOneErr` iterator. + pub(crate) fn new(first_two: (Option<I::Item>, Option<I::Item>), inner: I) -> Self { + Self { first_two, inner } + } +} + +impl<I> Iterator for ExactlyOneError<I> +where + I: Iterator, +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + self.first_two + .0 + .take() + .or_else(|| self.first_two.1.take()) + .or_else(|| self.inner.next()) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let mut additional_len = 0; + if self.first_two.0.is_some() { + additional_len += 1; + } + if self.first_two.1.is_some() { + additional_len += 1; + } + size_hint::add_scalar(self.inner.size_hint(), additional_len) + } +} + +impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {} |