itertools/
exactly_one_err.rs1#[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#[derive(Clone)]
22pub struct ExactlyOneError<I>
23where
24 I: Iterator,
25{
26 first_two: Option<Either<[I::Item; 2], I::Item>>,
27 inner: I,
28}
29
30impl<I> ExactlyOneError<I>
31where
32 I: Iterator,
33{
34 pub(crate) fn new(first_two: Option<Either<[I::Item; 2], I::Item>>, inner: I) -> Self {
36 Self { first_two, inner }
37 }
38
39 fn additional_len(&self) -> usize {
40 match self.first_two {
41 Some(Either::Left(_)) => 2,
42 Some(Either::Right(_)) => 1,
43 None => 0,
44 }
45 }
46}
47
48impl<I> Iterator for ExactlyOneError<I>
49where
50 I: Iterator,
51{
52 type Item = I::Item;
53
54 fn next(&mut self) -> Option<Self::Item> {
55 match self.first_two.take() {
56 Some(Either::Left([first, second])) => {
57 self.first_two = Some(Either::Right(second));
58 Some(first)
59 }
60 Some(Either::Right(second)) => Some(second),
61 None => self.inner.next(),
62 }
63 }
64
65 fn size_hint(&self) -> (usize, Option<usize>) {
66 size_hint::add_scalar(self.inner.size_hint(), self.additional_len())
67 }
68
69 fn count(self) -> usize
70 where
71 Self: Sized,
72 {
73 self.additional_len() + self.inner.count()
74 }
75
76 fn fold<B, F>(self, mut init: B, mut f: F) -> B
77 where
78 F: FnMut(B, Self::Item) -> B,
79 {
80 match self.first_two {
81 Some(Either::Left([first, second])) => {
82 init = f(init, first);
83 init = f(init, second);
84 }
85 Some(Either::Right(second)) => init = f(init, second),
86 None => {}
87 }
88 self.inner.fold(init, f)
89 }
90}
91
92impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {}
93
94impl<I> Display for ExactlyOneError<I>
95where
96 I: Iterator,
97{
98 fn fmt(&self, f: &mut Formatter) -> FmtResult {
99 let additional = self.additional_len();
100 if additional > 0 {
101 write!(f, "got at least 2 elements when exactly one was expected")
102 } else {
103 write!(f, "got zero elements when exactly one was expected")
104 }
105 }
106}
107
108impl<I> Debug for ExactlyOneError<I>
109where
110 I: Iterator + Debug,
111 I::Item: Debug,
112{
113 fn fmt(&self, f: &mut Formatter) -> FmtResult {
114 let mut dbg = f.debug_struct("ExactlyOneError");
115 match &self.first_two {
116 Some(Either::Left([first, second])) => {
117 dbg.field("first", first).field("second", second);
118 }
119 Some(Either::Right(second)) => {
120 dbg.field("second", second);
121 }
122 None => {}
123 }
124 dbg.field("inner", &self.inner).finish()
125 }
126}
127
128#[cfg(feature = "use_std")]
129impl<I> Error for ExactlyOneError<I>
130where
131 I: Iterator + Debug,
132 I::Item: Debug,
133{
134}