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;