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 where I: Iterator, { first_two: (Option, Option), inner: I, } impl ExactlyOneError where I: Iterator, { /// Creates a new `ExactlyOneErr` iterator. pub(crate) fn new(first_two: (Option, Option), inner: I) -> Self { Self { first_two, inner } } } impl Iterator for ExactlyOneError where I: Iterator, { type Item = I::Item; fn next(&mut self) -> Option { self.first_two .0 .take() .or_else(|| self.first_two.1.take()) .or_else(|| self.inner.next()) } fn size_hint(&self) -> (usize, Option) { 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 ExactSizeIterator for ExactlyOneError where I: ExactSizeIterator {}