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: ::Item, second: ::Item])) => {
55 self.first_two = Some(Either::Right(second));
56 Some(first)
57 },
58 Some(Either::Right(second: ::Item)) => {
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: usize = 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: &::Item, second: &::Item])) => {
95 write!(f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]", first, second, self.inner)
96 },
97 Some(Either::Right(second: &::Item)) => {
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
111