diff --git a/src/all_equal_value_err.rs b/src/all_equal_value_err.rs new file mode 100644 index 000000000..f3a1d3a4e --- /dev/null +++ b/src/all_equal_value_err.rs @@ -0,0 +1,31 @@ +#[cfg(doc)] +use crate::Itertools; +#[cfg(feature = "use_std")] +use std::error::Error; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; + +/// Value returned for the error case of [`Itertools::all_equal_value`]. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct AllEqualValueError(pub Option<[Item; 2]>); + +impl Display for AllEqualValueError { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + match self.0 { + None => { + write!( + f, + "got zero elements when all elements were expected to be equal" + ) + } + Some([_, _]) => { + write!( + f, + "got different elements when all elements were expected to be equal" + ) + } + } + } +} + +#[cfg(feature = "use_std")] +impl Error for AllEqualValueError where Item: Debug {} diff --git a/src/lib.rs b/src/lib.rs index 9f8d1cd1a..9bc81ddec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,6 +96,7 @@ pub mod structs { FilterOk, Interleave, InterleaveShortest, MapInto, MapOk, Positions, Product, PutBack, TakeWhileRef, TupleCombinations, Update, WhileSome, }; + pub use crate::all_equal_value_err::AllEqualValueError; #[cfg(feature = "use_alloc")] pub use crate::combinations::{ArrayCombinations, Combinations}; #[cfg(feature = "use_alloc")] @@ -177,6 +178,7 @@ pub use crate::either_or_both::EitherOrBoth; pub mod free; #[doc(inline)] pub use crate::free::*; +mod all_equal_value_err; #[cfg(feature = "use_alloc")] mod combinations; #[cfg(feature = "use_alloc")] @@ -2232,27 +2234,27 @@ pub trait Itertools: Iterator { /// two non-equal elements found. /// /// ``` - /// use itertools::Itertools; + /// use itertools::{Itertools, AllEqualValueError}; /// /// let data = vec![1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5]; - /// assert_eq!(data.iter().all_equal_value(), Err(Some((&1, &2)))); + /// assert_eq!(data.iter().all_equal_value(), Err(AllEqualValueError(Some([&1, &2])))); /// assert_eq!(data[0..3].iter().all_equal_value(), Ok(&1)); /// assert_eq!(data[3..5].iter().all_equal_value(), Ok(&2)); /// assert_eq!(data[5..8].iter().all_equal_value(), Ok(&3)); /// /// let data : Option = None; - /// assert_eq!(data.into_iter().all_equal_value(), Err(None)); + /// assert_eq!(data.into_iter().all_equal_value(), Err(AllEqualValueError(None))); /// ``` #[allow(clippy::type_complexity)] - fn all_equal_value(&mut self) -> Result> + fn all_equal_value(&mut self) -> Result> where Self: Sized, Self::Item: PartialEq, { - let first = self.next().ok_or(None)?; + let first = self.next().ok_or(AllEqualValueError(None))?; let other = self.find(|x| x != &first); if let Some(other) = other { - Err(Some((first, other))) + Err(AllEqualValueError(Some([first, other]))) } else { Ok(first) } diff --git a/tests/test_std.rs b/tests/test_std.rs index ad391faad..a02fcc0e8 100644 --- a/tests/test_std.rs +++ b/tests/test_std.rs @@ -9,6 +9,7 @@ use crate::it::multipeek; use crate::it::multizip; use crate::it::peek_nth; use crate::it::repeat_n; +use crate::it::AllEqualValueError; use crate::it::ExactlyOneError; use crate::it::FoldWhile; use crate::it::Itertools; @@ -282,14 +283,17 @@ fn all_equal() { #[test] fn all_equal_value() { - assert_eq!("".chars().all_equal_value(), Err(None)); + assert_eq!("".chars().all_equal_value(), Err(AllEqualValueError(None))); assert_eq!("A".chars().all_equal_value(), Ok('A')); - assert_eq!("AABBCCC".chars().all_equal_value(), Err(Some(('A', 'B')))); + assert_eq!( + "AABBCCC".chars().all_equal_value(), + Err(AllEqualValueError(Some(['A', 'B']))) + ); assert_eq!("AAAAAAA".chars().all_equal_value(), Ok('A')); { let mut it = [1, 2, 3].iter().copied(); let result = it.all_equal_value(); - assert_eq!(result, Err(Some((1, 2)))); + assert_eq!(result, Err(AllEqualValueError(Some([1, 2])))); let remaining = it.next(); assert_eq!(remaining, Some(3)); assert!(it.next().is_none());