Skip to main content

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}