1 #[cfg(feature = "use_std")] 2 use std::error::Error; 3 use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; 4 5 use std::iter::ExactSizeIterator; 6 7 use either::Either; 8 9 use 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)] 20 pub struct ExactlyOneError<I> 21 where 22 I: Iterator, 23 { 24 first_two: Option<Either<[I::Item; 2], I::Item>>, 25 inner: I, 26 } 27 28 impl<I> ExactlyOneError<I> 29 where 30 I: Iterator, 31 { 32 /// Creates a new `ExactlyOneErr` iterator. new(first_two: Option<Either<[I::Item; 2], I::Item>>, inner: I) -> Self33 pub(crate) fn new(first_two: Option<Either<[I::Item; 2], I::Item>>, inner: I) -> Self { 34 Self { first_two, inner } 35 } 36 additional_len(&self) -> usize37 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 46 impl<I> Iterator for ExactlyOneError<I> 47 where 48 I: Iterator, 49 { 50 type Item = I::Item; 51 next(&mut self) -> Option<Self::Item>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)) => Some(second), 59 None => self.inner.next(), 60 } 61 } 62 size_hint(&self) -> (usize, Option<usize>)63 fn size_hint(&self) -> (usize, Option<usize>) { 64 size_hint::add_scalar(self.inner.size_hint(), self.additional_len()) 65 } 66 fold<B, F>(self, mut init: B, mut f: F) -> B where F: FnMut(B, Self::Item) -> B,67 fn fold<B, F>(self, mut init: B, mut f: F) -> B 68 where 69 F: FnMut(B, Self::Item) -> B, 70 { 71 match self.first_two { 72 Some(Either::Left([first, second])) => { 73 init = f(init, first); 74 init = f(init, second); 75 } 76 Some(Either::Right(second)) => init = f(init, second), 77 None => {} 78 } 79 self.inner.fold(init, f) 80 } 81 } 82 83 impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {} 84 85 impl<I> Display for ExactlyOneError<I> 86 where 87 I: Iterator, 88 { fmt(&self, f: &mut Formatter) -> FmtResult89 fn fmt(&self, f: &mut Formatter) -> FmtResult { 90 let additional = self.additional_len(); 91 if additional > 0 { 92 write!(f, "got at least 2 elements when exactly one was expected") 93 } else { 94 write!(f, "got zero elements when exactly one was expected") 95 } 96 } 97 } 98 99 impl<I> Debug for ExactlyOneError<I> 100 where 101 I: Iterator + Debug, 102 I::Item: Debug, 103 { fmt(&self, f: &mut Formatter) -> FmtResult104 fn fmt(&self, f: &mut Formatter) -> FmtResult { 105 let mut dbg = f.debug_struct("ExactlyOneError"); 106 match &self.first_two { 107 Some(Either::Left([first, second])) => { 108 dbg.field("first", first).field("second", second); 109 } 110 Some(Either::Right(second)) => { 111 dbg.field("second", second); 112 } 113 None => {} 114 } 115 dbg.field("inner", &self.inner).finish() 116 } 117 } 118 119 #[cfg(feature = "use_std")] 120 impl<I> Error for ExactlyOneError<I> 121 where 122 I: Iterator + Debug, 123 I::Item: Debug, 124 { 125 } 126