zhc_utils/iter/all_eq.rs
1//! Equality check across all elements of an iterator.
2//!
3//! This module provides the [`AllEq`] extension trait, which adds a method to test whether every
4//! element in an iterator is equal to every other. It is automatically implemented for any
5//! iterator whose items implement `PartialEq`.
6//!
7//! # Example
8//!
9//! ```rust,no_run
10//! # use zhc_utils::iter::AllEq;
11//! let uniform = vec![7, 7, 7, 7];
12//! assert_eq!(uniform.into_iter().all_eq(), Some(true));
13//!
14//! let mixed = vec![1, 2, 1];
15//! assert_eq!(mixed.into_iter().all_eq(), Some(false));
16//! ```
17
18/// An extension trait that checks whether all elements of an iterator are equal.
19///
20/// `AllEq` is automatically implemented for any iterator whose items implement `PartialEq`.
21/// Importing this trait brings the [`all_eq`](AllEq::all_eq) method into scope.
22pub trait AllEq {
23 /// Consumes the iterator and checks whether all elements are equal to each other.
24 ///
25 /// This method compares every element to the first using `PartialEq`. It returns `Some(true)`
26 /// if all elements are equal, `Some(false)` if any element differs from the first, or `None`
27 /// if the iterator is empty. A single-element iterator always returns `Some(true)`.
28 ///
29 /// The check short-circuits: iteration stops as soon as a non-equal element is found.
30 ///
31 /// # Example
32 ///
33 /// ```rust,no_run
34 /// # use zhc_utils::iter::AllEq;
35 /// assert_eq!([5, 5, 5].into_iter().all_eq(), Some(true));
36 /// assert_eq!([5, 5, 6].into_iter().all_eq(), Some(false));
37 /// assert_eq!(std::iter::empty::<i32>().all_eq(), None);
38 /// ```
39 fn all_eq(self) -> Option<bool>;
40}
41
42impl<I: Iterator<Item = T>, T: PartialEq> AllEq for I {
43 fn all_eq(mut self) -> Option<bool> {
44 let Some(first) = self.next() else {
45 return None;
46 };
47 Some(self.all(|a| a == first))
48 }
49}
50
51#[cfg(test)]
52mod tests {
53
54 use super::*;
55
56 #[test]
57 fn test_empty_iterator() {
58 let empty: Vec<i32> = vec![];
59 assert_eq!(empty.into_iter().all_eq(), None);
60 }
61
62 #[test]
63 fn test_single_element() {
64 let single = vec![42];
65 assert_eq!(single.into_iter().all_eq(), Some(true));
66 }
67
68 #[test]
69 fn test_all_equal_elements() {
70 let all_same = vec![5, 5, 5, 5];
71 assert_eq!(all_same.into_iter().all_eq(), Some(true));
72 }
73
74 #[test]
75 fn test_not_all_equal_elements() {
76 let mixed = vec![1, 2, 3];
77 assert_eq!(mixed.into_iter().all_eq(), Some(false));
78 }
79
80 #[test]
81 fn test_partially_equal_elements() {
82 let partial = vec![7, 7, 8, 7];
83 assert_eq!(partial.into_iter().all_eq(), Some(false));
84 }
85}