iterators_collection/share/
mod.rs

1//! A module about advanced memory sharing during iteration
2
3/// Iterates twice over the same collection
4/// 
5/// # Example
6/// The following code
7/// 
8/// ```
9/// use iterators_collection::share::DoubleIterator;
10/// 
11/// let mut array = [1, 2, 3, 4, 5];
12/// let iter = DoubleIterator::new(&mut array);
13/// 
14/// for (i, j) in iter {
15///     // Some code here
16/// }
17/// ```
18/// 
19/// Means the same as
20/// 
21/// ```
22/// let array = [1, 2, 3, 4, 5];
23/// for i in array.iter() {
24///     for j in array.iter() {
25///         // Some code here
26///     }
27/// }
28/// ```
29/// 
30/// with some differences:
31/// - i and j will never be the same with `DoubleIterator`
32/// 
33/// - you can safely iterate on a mutable slice with `DoubleIterator`
34/// 
35/// - i and j CANNOT be shared across threads because it is unsafe to increment the iterator in one thread while accessing one of these references from the other one. It may lead to a data race
36/// 
37/// - i and j are raw pointers and not references because the correct lifetime for the borrowed values is not known at compile time since a simple call to the `next` method may lead to a data race because two mutable references to the same object may exist
38/// 
39/// Since version 0.3.0, the preferred way to do it is to use the `safe_for_each` method because you can use this iterator without writting unsafe code
40/// ```
41/// use iterators_collection::share::DoubleIterator;
42/// 
43/// let mut array = [1, 2, 3, 4, 5];
44/// let iter = DoubleIterator::new(&mut array);
45/// 
46/// iter.safe_for_each(|i, j| {
47///     // Some code here
48/// });
49/// ```
50pub struct DoubleIterator<'a, T> {
51    slice: &'a mut [T],
52    first: usize,
53    second: usize,
54}
55
56impl<'a, T> DoubleIterator<'a, T> {
57    /// Creates a `DoubleIterator` from a slice
58    /// 
59    /// # Panics
60    /// Panics if `slice.len() < 2`
61    pub fn new(slice: &'a mut [T]) -> Self {
62        assert!(slice.len() >= 2);
63
64        Self {
65            slice,
66
67            first: 0,
68            second: 1,
69        }
70    }
71
72    /// Returns a mutable pointer to the `index`th element of the borrowed slice
73    /// 
74    /// # Unsafety
75    /// Indexes are not checked if the `debug_assert!`s are disabled
76    /// 
77    /// This pointer is unsafe to use
78    unsafe fn nth_ptr(&mut self, index: usize) -> *mut T {
79        debug_assert!(index < self.slice.len());
80        self.slice.get_unchecked_mut(index) as *mut T
81    }
82
83    /// Increments the indexes `first` and `second` or returns Err
84    fn increment(&mut self) -> Result<(), ()> {
85        loop {
86            // Increment
87            self.second += 1;
88
89            // Check for overflow
90            if self.second == self.slice.len() {
91                self.second = 0;
92                self.first += 1;
93
94                if self.first >= self.slice.len() {
95                    return Err(());
96                }
97            }
98
99            if self.first != self.second {
100                return Ok(());
101            }
102        }
103    }
104
105    /// Runs the given closure in a safe context
106    /// 
107    /// # Example
108    /// ```
109    /// use iterators_collection::share::DoubleIterator;
110    /// 
111    /// let mut array = [1, 2, 3, 4, 5];
112    /// let iter = DoubleIterator::new(&mut array);
113    /// 
114    /// iter.safe_for_each(|i, j| {
115    ///     println!("Got i = {} and j = {}", i, j);
116    ///     assert_ne!(i, j);
117    /// });
118    /// ```
119    /// 
120    /// # Notes
121    /// Not like a legacy iteration using a `for` loop, i and j are references because it's safe to use in this context
122    pub fn safe_for_each<F: Fn(&mut T, &mut T)>(self, callback: F) {
123        for (i, j) in self {
124            unsafe {
125                callback(&mut *i, &mut *j);
126            }
127        }
128    }
129
130    /// Sets the position of the iterator
131    /// 
132    /// # Parameters
133    /// `i` the position of the first pointer of the tuple returned by the `Iterator` trait's implementation
134    /// 
135    /// `j` the position of the second one
136    /// 
137    /// # Panics
138    /// Panics if either `i` or `j` are out of range (greater or equal to `slice.len()`)
139    /// 
140    /// Panics if `i == j`
141    pub fn set(&mut self, i: usize, j: usize) {
142        assert_ne!(i, j);
143        assert!(i < self.slice.len() && j < self.slice.len());
144
145        self.first = i;
146        self.second = j;
147    }
148}
149
150impl<T> crate::ResettableIterator for DoubleIterator<'_, T> {
151    fn reset(&mut self) {
152        self.first = 0;
153        self.second = 1;
154    }
155}
156
157impl<T> Iterator for DoubleIterator<'_, T> {
158    type Item = (*mut T, *mut T);
159
160    fn next(&mut self) -> Option<Self::Item> {
161        if self.first == self.slice.len() {
162            return None;
163        }
164
165        let returned = Some(unsafe { (self.nth_ptr(self.first), self.nth_ptr(self.second)) });
166        std::mem::drop(self.increment()); // Dropping is a way to ignore the error which doesn't matter here
167
168        returned
169    }
170}
171
172/// A `DoubleIterator` iterating on one single "line" (see explanation below)
173/// 
174/// # Introduction
175/// The iteration cycle of a `DoubleIterator` can be seen as a matrix with `i` as the value of the line and `j` as the value of the collumn. For example, in an array as `[0, 1, 2, 3, 4]`, a `DoubleIterator` will return the numbered cells and discard the blanks
176/// ```text
177/// +---+---+---+---+---+---+
178/// |   |i=0|i=1|i=2|i=3|i=4|
179/// +---+---+---+---+---+---+
180/// |j=0|   | 1 | 2 | 3 | 4 |
181/// +---+---+---+---+---+---+
182/// |j=1| 5 |   | 6 | 7 | 8 |
183/// +---+---+---+---+---+---+
184/// |j=2| 9 |10 |   |11 |12 |
185/// +---+---+---+---+---+---+
186/// |j=3|13 |14 |15 |   |16 |
187/// +---+---+---+---+---+---+
188/// |j=4|17 |18 |19 |20 |   |
189/// +---+---+---+---+---+---+
190/// ```
191/// 
192/// In this example, the first iterator tuple returned (once the two members dereferenced) is `(0, 1)`, then `(0, 2)`, `(0, 3)`, `(0, 4)`, and at the end of line, `i` is reset and `j` is incrememented, returning `(1, 0)`, `(1, 2)` because there is a blank in the cell (`i=1`; `j=1`), `(1, 3)`...
193/// 
194/// The blanks are here because there can't be two mutable references on the same object.
195/// 
196/// But in some cases, you need to iterate only on one single line and not the whole grid, that's why `SingleLineIterator` exists.
197/// 
198/// # Hey, wait! Why using that iterator and not simply iterating manually?
199/// Just like `DoubleIterator` does, this iterator returns two raw pointers to a member of the slice to iterate
200/// 
201/// Since version 0.3.3, the prefered way to do this is to use the `safe_for_each` method
202pub struct SingleLineIterator<'a, T> {
203    slice: &'a mut [T],
204    index: usize,
205    cur: usize,
206}
207
208impl<'a, T> SingleLineIterator<'a, T> {
209    /// Returns a new `SingleLineIterator` which returns a tuple of a mutable reference to `slice[index]` and to another member of `slice` at each iteration
210    /// 
211    /// # Panics
212    /// Panics if `index` is greater or equal to `slice.len()`
213    pub fn new(slice: &'a mut [T], index: usize) -> Self {
214        assert!(index < slice.len());
215
216        Self {
217            slice,
218            index,
219            cur: if index == 0 {
220                1
221            } else {
222                0
223            },
224        }
225    }
226
227    /// Runs the given closure in a safe context
228    /// 
229    /// # Example
230    /// ```
231    /// use iterators_collection::share::SingleLineIterator;
232    /// 
233    /// let mut array = [1, 2, 3, 4, 5];
234    /// let iter = SingleLineIterator::new(&mut array, 0);
235    /// 
236    /// iter.safe_for_each(|i, j| {
237    ///     println!("Got i = {} and j = {}", i, j);
238    ///     assert_ne!(i, j);
239    /// });
240    /// ```
241    /// 
242    /// # Notes
243    /// Not like a legacy iteration using a `for` loop, i and j are references because it's safe to use in this context
244    pub fn safe_for_each<F: Fn(&mut T, &mut T)>(self, callback: F) {
245        for (i, j) in self {
246            unsafe {
247                callback(&mut *i, &mut *j);
248            }
249        }
250    }
251}
252
253impl<T> crate::ResettableIterator for SingleLineIterator<'_, T> {
254    fn reset(&mut self) {
255        self.cur = 0;
256    }
257}
258
259impl<'a, T> Iterator for SingleLineIterator<'a, T> {
260    type Item = (*mut T, *mut T);
261
262    fn next(&mut self) -> Option<Self::Item> {
263        let returned = if self.cur >= self.slice.len() {
264            None
265        } else {
266            unsafe {
267                let ptr1 = self.slice.get_unchecked_mut(self.index) as *mut T;
268                let ptr2 = self.slice.get_unchecked_mut(self.cur)   as *mut T;
269
270                Some((ptr1, ptr2))
271            }
272        };
273
274        self.cur += 1;
275        if self.cur == self.index {
276            self.cur += 1;
277        }
278
279        returned
280    }
281}
282
283impl<'a, T> From<DoubleIterator<'a, T>> for SingleLineIterator<'a, T> {
284    fn from(src: DoubleIterator<'a, T>) -> Self {
285        Self {
286            cur: src.second,
287            index: src.first,
288            slice: src.slice,
289        }
290    }
291}
292
293
294#[cfg(test)]
295mod tests;