self_compare/
lib.rs

1#![warn(missing_docs)]
2//! A crate for comparing all elements of a slice with themselves
3
4mod ext;
5pub use ext::*;
6
7/// A structure for immutably comparing the elemnts of a slice with themselves
8///
9/// Implements `Iterator` since the references don't need to be unique
10pub struct Comparer<'a, T: 'a> {
11    list: &'a [T],
12    i: usize,
13    j: usize,
14}
15
16impl<'a, T: 'a> Comparer<'a , T> {
17    /// Returns a `Comparer`
18    pub fn new(list: &'a [T]) -> Self {
19        Comparer {
20            list,
21            i: 0,
22            j: 1,
23        }
24    }
25    /// Returns the inner slice
26    pub fn inner(&self) -> &[T] {
27        self.list
28    }
29    /// Returns the indices of the next two elements to be compared
30    pub fn indices(&self) -> (usize, usize) {
31        (self.i, self.j)
32    }
33    /// Same as `next()` but also returns the indices of the elements
34    pub fn next_enumerated(&mut self) -> Option<((usize, &T), (usize, &T))> {
35        let (i, j) = (self.i, self.j);
36        self.next().map(|(a, b)| ((i, a), (j, b)))
37    }
38}
39
40impl<'a, T: 'a> Iterator for Comparer<'a, T> {
41    type Item = (&'a T, &'a T);
42
43    fn next(&mut self) -> Option<Self::Item> {
44        if self.list.is_empty() || self.i == self.list.len()-1 {
45            return None;
46        }
47        let (x, y) = (self.i, self.j);
48
49        self.j += 1;
50        if self.j == self.list.len() {
51            self.i += 1;
52            self.j = self.i + 1;
53        }
54
55        Some((&self.list[x], &self.list[y]))
56    }
57}
58
59/// A structure for mutably comparing the elements of a slice with themselves
60pub struct ComparerMut<'a, T: 'a> {
61    list: &'a mut [T],
62    i: usize,
63    j: usize,
64}
65
66impl<'a, T: 'a> ComparerMut<'a, T> {
67    /// Returns a `ComparerMut`
68    pub fn new(list: &'a mut [T]) -> Self {
69        ComparerMut {
70            list,
71            i: 0,
72            j: 1,
73        }
74    }
75    /// Returns the inner mutable slice
76    pub fn inner(&mut self) -> &mut [T] {
77        self.list
78    }
79    /// Returns the indices of the next two elements to be compared
80    pub fn indices(&self) -> (usize, usize) {
81        (self.i, self.j)
82    }
83    /// Optionally returns mutable reference to two elements until all elements have been compared
84    pub fn next(&mut self) -> Option<(&mut T, &mut T)> {
85        if self.list.is_empty() || self.i == self.list.len()-1 {
86            return None;
87        }
88        let (x, y) = (self.i, self.j);
89
90        self.j += 1;
91        if self.j == self.list.len() {
92            self.i += 1;
93            self.j = self.i + 1;
94        }
95
96        Some(unsafe {
97            (self.list.as_mut_ptr().offset(x as isize).as_mut().unwrap(),
98            self.list.as_mut_ptr().offset(y as isize).as_mut().unwrap())
99        })
100    }
101    /// Same as `next()` but also returns the indices of the elements
102    pub fn next_enumerated(&mut self) -> Option<((usize, &mut T), (usize, &mut T))> {
103        let (i, j) = (self.i, self.j);
104        self.next().map(|(a, b)| ((i, a), (j, b)))
105    }
106}
107
108#[cfg(test)]
109mod mut_tests {
110    use super::*;
111
112    #[test]
113    fn empty() {
114        let mut v: [i32; 0] = [];
115        let mut c = v.self_comparer_mut();
116
117        assert!(c.next().is_none())
118    }
119    #[test]
120    fn one_element() {
121        let mut v = [1];
122        let mut c = v.self_comparer_mut();
123
124        assert!(c.next().is_none())
125    }
126    #[test]
127    fn two_elements() {
128        let mut v = [1, 2];
129        let mut c = v.self_comparer_mut();
130
131        assert_eq!(c.next(), Some((&mut 1, &mut 2)));
132        assert!(c.next().is_none());
133    }
134    #[test]
135    fn compare_and_enumerate_yield_the_same() {
136        let mut v: Vec<_> = (0..100).collect();
137
138        let mut regular_comparisons = Vec::new();
139        let mut enumerated_comparisons = Vec::new();
140
141        v.compare_self_mut(|a, b| regular_comparisons.push((*a, *b)));
142        v.compare_self_enumerated_mut(|(_, a), (_, b)| enumerated_comparisons.push((*a, *b)));
143
144        assert_eq!(regular_comparisons, enumerated_comparisons)
145    }
146    #[test]
147    fn all_compare_0() {
148        all_compare(0);
149    }
150    #[test]
151    fn all_compare_1() {
152        all_compare(1);
153    }
154    #[test]
155    fn all_compare_1000() {
156        all_compare(1000);
157    }
158    fn all_compare(size: usize) {
159        let mut vec = vec![Vec::with_capacity(size.saturating_sub(1)); size];
160
161        vec.compare_self_enumerated_mut(|(i, a), (j, b)| {
162            let id = a.binary_search(&j).unwrap_err();
163            a.insert(id, j);
164            let id = b.binary_search(&i).unwrap_err();
165            b.insert(id, i);
166        });
167
168        assert!(vec
169            .into_iter()
170            .enumerate()
171            .map(|(i, v)| v.into_iter().zip((0..size).filter(move |x| x != &i)))
172            .all(|mut v| v.all(|(a, b)| a == b))
173        );
174    }
175}
176#[cfg(test)]
177mod tests {
178    use super::*;
179
180    #[test]
181    fn empty() {
182        let v: [i32; 0] = [];
183        let mut c = v.self_comparer();
184
185        assert!(c.next().is_none())
186    }
187    #[test]
188    fn one_element() {
189        let v = [1];
190        let mut c = v.self_comparer();
191
192        assert!(c.next().is_none())
193    }
194    #[test]
195    fn two_elements() {
196        let v = [1, 2];
197        let mut c = v.self_comparer();
198
199        assert_eq!(c.next(), Some((&1, &2)));
200        assert!(c.next().is_none());
201    }
202    #[test]
203    fn compare_and_enumerate_yield_the_same() {
204        let v: Vec<_> = (0..100).collect();
205
206        let mut regular_comparisons = Vec::new();
207        let mut enumerated_comparisons = Vec::new();
208
209        v.compare_self(|a, b| regular_comparisons.push((*a, *b)));
210        v.compare_self_enumerated(|(_, a), (_, b)| enumerated_comparisons.push((*a, *b)));
211
212        assert_eq!(regular_comparisons, enumerated_comparisons)
213    }
214}