itertools/
exactly_one_err.rs

1#[cfg(feature = "use_std")]
2use std::error::Error;
3use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
4
5use std::iter::ExactSizeIterator;
6
7use either::Either;
8
9use crate::size_hint;
10
11/// Iterator returned for the error case of `IterTools::exactly_one()`
12/// This iterator yields exactly the same elements as the input iterator.
13///
14/// During the execution of `exactly_one` the iterator must be mutated.  This wrapper
15/// effectively "restores" the state of the input iterator when it's handed back.
16///
17/// This is very similar to `PutBackN` except this iterator only supports 0-2 elements and does not
18/// use a `Vec`.
19#[derive(Clone)]
20pub struct ExactlyOneError<I>
21where
22    I: Iterator,
23{
24    first_two: Option<Either<[I::Item; 2], I::Item>>,
25    inner: I,
26}
27
28impl<I> ExactlyOneError<I>
29where
30    I: Iterator,
31{
32    /// Creates a new `ExactlyOneErr` iterator.
33    pub(crate) fn new(first_two: Option<Either<[I::Item; 2], I::Item>>, inner: I) -> Self {
34        Self { first_two, inner }
35    }
36
37    fn additional_len(&self) -> usize {
38        match self.first_two {
39            Some(Either::Left(_)) => 2,
40            Some(Either::Right(_)) => 1,
41            None => 0,
42        }
43    }
44}
45
46impl<I> Iterator for ExactlyOneError<I>
47where
48    I: Iterator,
49{
50    type Item = I::Item;
51
52    fn next(&mut self) -> Option<Self::Item> {
53        match self.first_two.take() {
54            Some(Either::Left([first, second])) => {
55                self.first_two = Some(Either::Right(second));
56                Some(first)
57            },
58            Some(Either::Right(second)) => {
59                Some(second)
60            }
61            None => {
62                self.inner.next()
63            }
64        }
65    }
66
67    fn size_hint(&self) -> (usize, Option<usize>) {
68        size_hint::add_scalar(self.inner.size_hint(), self.additional_len())
69    }
70}
71
72
73impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {}
74
75impl<I> Display for ExactlyOneError<I> 
76    where I: Iterator,
77{
78    fn fmt(&self, f: &mut Formatter) -> FmtResult {
79        let additional = self.additional_len();
80        if additional > 0 {
81            write!(f, "got at least 2 elements when exactly one was expected")
82        } else {
83            write!(f, "got zero elements when exactly one was expected")
84        }
85    }
86}
87
88impl<I> Debug for ExactlyOneError<I> 
89    where I: Iterator + Debug,
90          I::Item: Debug,
91{
92    fn fmt(&self, f: &mut Formatter) -> FmtResult {
93        match &self.first_two {
94            Some(Either::Left([first, second])) => {
95                write!(f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]", first, second, self.inner)
96            },
97            Some(Either::Right(second)) => {
98                write!(f, "ExactlyOneError[Second: {:?}, RemainingIter: {:?}]", second, self.inner)
99            }
100            None => {
101                write!(f, "ExactlyOneError[RemainingIter: {:?}]", self.inner)
102            }
103        }
104    }
105}
106
107#[cfg(feature = "use_std")]
108impl<I> Error for ExactlyOneError<I>  where I: Iterator + Debug, I::Item: Debug, {}
109
110