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)) => { 59 Some(second) 60 } 61 None => { 62 self.inner.next() 63 } 64 } 65 } 66 size_hint(&self) -> (usize, Option<usize>)67 fn size_hint(&self) -> (usize, Option<usize>) { 68 size_hint::add_scalar(self.inner.size_hint(), self.additional_len()) 69 } 70 } 71 72 73 impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {} 74 75 impl<I> Display for ExactlyOneError<I> 76 where I: Iterator, 77 { fmt(&self, f: &mut Formatter) -> FmtResult78 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 88 impl<I> Debug for ExactlyOneError<I> 89 where I: Iterator + Debug, 90 I::Item: Debug, 91 { fmt(&self, f: &mut Formatter) -> FmtResult92 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")] 108 impl<I> Error for ExactlyOneError<I> where I: Iterator + Debug, I::Item: Debug, {} 109 110 111