1 use crate::iter::plumbing::*;
2 use crate::iter::*;
3 use crate::math::div_round_up;
4 
5 /// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.
6 #[derive(Debug)]
7 pub struct RChunks<'data, T: Sync> {
8     chunk_size: usize,
9     slice: &'data [T],
10 }
11 
12 impl<'data, T: Sync> RChunks<'data, T> {
new(chunk_size: usize, slice: &'data [T]) -> Self13     pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
14         Self { chunk_size, slice }
15     }
16 }
17 
18 impl<'data, T: Sync> Clone for RChunks<'data, T> {
clone(&self) -> Self19     fn clone(&self) -> Self {
20         RChunks { ..*self }
21     }
22 }
23 
24 impl<'data, T: Sync + 'data> ParallelIterator for RChunks<'data, T> {
25     type Item = &'data [T];
26 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,27     fn drive_unindexed<C>(self, consumer: C) -> C::Result
28     where
29         C: UnindexedConsumer<Self::Item>,
30     {
31         bridge(self, consumer)
32     }
33 
opt_len(&self) -> Option<usize>34     fn opt_len(&self) -> Option<usize> {
35         Some(self.len())
36     }
37 }
38 
39 impl<'data, T: Sync + 'data> IndexedParallelIterator for RChunks<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,40     fn drive<C>(self, consumer: C) -> C::Result
41     where
42         C: Consumer<Self::Item>,
43     {
44         bridge(self, consumer)
45     }
46 
len(&self) -> usize47     fn len(&self) -> usize {
48         div_round_up(self.slice.len(), self.chunk_size)
49     }
50 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,51     fn with_producer<CB>(self, callback: CB) -> CB::Output
52     where
53         CB: ProducerCallback<Self::Item>,
54     {
55         callback.callback(RChunksProducer {
56             chunk_size: self.chunk_size,
57             slice: self.slice,
58         })
59     }
60 }
61 
62 struct RChunksProducer<'data, T: Sync> {
63     chunk_size: usize,
64     slice: &'data [T],
65 }
66 
67 impl<'data, T: 'data + Sync> Producer for RChunksProducer<'data, T> {
68     type Item = &'data [T];
69     type IntoIter = ::std::slice::RChunks<'data, T>;
70 
into_iter(self) -> Self::IntoIter71     fn into_iter(self) -> Self::IntoIter {
72         self.slice.rchunks(self.chunk_size)
73     }
74 
split_at(self, index: usize) -> (Self, Self)75     fn split_at(self, index: usize) -> (Self, Self) {
76         let elem_index = self.slice.len().saturating_sub(index * self.chunk_size);
77         let (left, right) = self.slice.split_at(elem_index);
78         (
79             RChunksProducer {
80                 chunk_size: self.chunk_size,
81                 slice: right,
82             },
83             RChunksProducer {
84                 chunk_size: self.chunk_size,
85                 slice: left,
86             },
87         )
88     }
89 }
90 
91 /// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.
92 #[derive(Debug)]
93 pub struct RChunksExact<'data, T: Sync> {
94     chunk_size: usize,
95     slice: &'data [T],
96     rem: &'data [T],
97 }
98 
99 impl<'data, T: Sync> RChunksExact<'data, T> {
new(chunk_size: usize, slice: &'data [T]) -> Self100     pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
101         let rem_len = slice.len() % chunk_size;
102         let (rem, slice) = slice.split_at(rem_len);
103         Self {
104             chunk_size,
105             slice,
106             rem,
107         }
108     }
109 
110     /// Return the remainder of the original slice that is not going to be
111     /// returned by the iterator. The returned slice has at most `chunk_size-1`
112     /// elements.
remainder(&self) -> &'data [T]113     pub fn remainder(&self) -> &'data [T] {
114         self.rem
115     }
116 }
117 
118 impl<'data, T: Sync> Clone for RChunksExact<'data, T> {
clone(&self) -> Self119     fn clone(&self) -> Self {
120         RChunksExact { ..*self }
121     }
122 }
123 
124 impl<'data, T: Sync + 'data> ParallelIterator for RChunksExact<'data, T> {
125     type Item = &'data [T];
126 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,127     fn drive_unindexed<C>(self, consumer: C) -> C::Result
128     where
129         C: UnindexedConsumer<Self::Item>,
130     {
131         bridge(self, consumer)
132     }
133 
opt_len(&self) -> Option<usize>134     fn opt_len(&self) -> Option<usize> {
135         Some(self.len())
136     }
137 }
138 
139 impl<'data, T: Sync + 'data> IndexedParallelIterator for RChunksExact<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,140     fn drive<C>(self, consumer: C) -> C::Result
141     where
142         C: Consumer<Self::Item>,
143     {
144         bridge(self, consumer)
145     }
146 
len(&self) -> usize147     fn len(&self) -> usize {
148         self.slice.len() / self.chunk_size
149     }
150 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,151     fn with_producer<CB>(self, callback: CB) -> CB::Output
152     where
153         CB: ProducerCallback<Self::Item>,
154     {
155         callback.callback(RChunksExactProducer {
156             chunk_size: self.chunk_size,
157             slice: self.slice,
158         })
159     }
160 }
161 
162 struct RChunksExactProducer<'data, T: Sync> {
163     chunk_size: usize,
164     slice: &'data [T],
165 }
166 
167 impl<'data, T: 'data + Sync> Producer for RChunksExactProducer<'data, T> {
168     type Item = &'data [T];
169     type IntoIter = ::std::slice::RChunksExact<'data, T>;
170 
into_iter(self) -> Self::IntoIter171     fn into_iter(self) -> Self::IntoIter {
172         self.slice.rchunks_exact(self.chunk_size)
173     }
174 
split_at(self, index: usize) -> (Self, Self)175     fn split_at(self, index: usize) -> (Self, Self) {
176         let elem_index = self.slice.len() - index * self.chunk_size;
177         let (left, right) = self.slice.split_at(elem_index);
178         (
179             RChunksExactProducer {
180                 chunk_size: self.chunk_size,
181                 slice: right,
182             },
183             RChunksExactProducer {
184                 chunk_size: self.chunk_size,
185                 slice: left,
186             },
187         )
188     }
189 }
190 
191 /// Parallel iterator over mutable non-overlapping chunks of a slice, starting at the end.
192 #[derive(Debug)]
193 pub struct RChunksMut<'data, T: Send> {
194     chunk_size: usize,
195     slice: &'data mut [T],
196 }
197 
198 impl<'data, T: Send> RChunksMut<'data, T> {
new(chunk_size: usize, slice: &'data mut [T]) -> Self199     pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {
200         Self { chunk_size, slice }
201     }
202 }
203 
204 impl<'data, T: Send + 'data> ParallelIterator for RChunksMut<'data, T> {
205     type Item = &'data mut [T];
206 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,207     fn drive_unindexed<C>(self, consumer: C) -> C::Result
208     where
209         C: UnindexedConsumer<Self::Item>,
210     {
211         bridge(self, consumer)
212     }
213 
opt_len(&self) -> Option<usize>214     fn opt_len(&self) -> Option<usize> {
215         Some(self.len())
216     }
217 }
218 
219 impl<'data, T: Send + 'data> IndexedParallelIterator for RChunksMut<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,220     fn drive<C>(self, consumer: C) -> C::Result
221     where
222         C: Consumer<Self::Item>,
223     {
224         bridge(self, consumer)
225     }
226 
len(&self) -> usize227     fn len(&self) -> usize {
228         div_round_up(self.slice.len(), self.chunk_size)
229     }
230 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,231     fn with_producer<CB>(self, callback: CB) -> CB::Output
232     where
233         CB: ProducerCallback<Self::Item>,
234     {
235         callback.callback(RChunksMutProducer {
236             chunk_size: self.chunk_size,
237             slice: self.slice,
238         })
239     }
240 }
241 
242 struct RChunksMutProducer<'data, T: Send> {
243     chunk_size: usize,
244     slice: &'data mut [T],
245 }
246 
247 impl<'data, T: 'data + Send> Producer for RChunksMutProducer<'data, T> {
248     type Item = &'data mut [T];
249     type IntoIter = ::std::slice::RChunksMut<'data, T>;
250 
into_iter(self) -> Self::IntoIter251     fn into_iter(self) -> Self::IntoIter {
252         self.slice.rchunks_mut(self.chunk_size)
253     }
254 
split_at(self, index: usize) -> (Self, Self)255     fn split_at(self, index: usize) -> (Self, Self) {
256         let elem_index = self.slice.len().saturating_sub(index * self.chunk_size);
257         let (left, right) = self.slice.split_at_mut(elem_index);
258         (
259             RChunksMutProducer {
260                 chunk_size: self.chunk_size,
261                 slice: right,
262             },
263             RChunksMutProducer {
264                 chunk_size: self.chunk_size,
265                 slice: left,
266             },
267         )
268     }
269 }
270 
271 /// Parallel iterator over mutable non-overlapping chunks of a slice, starting at the end.
272 #[derive(Debug)]
273 pub struct RChunksExactMut<'data, T: Send> {
274     chunk_size: usize,
275     slice: &'data mut [T],
276     rem: &'data mut [T],
277 }
278 
279 impl<'data, T: Send> RChunksExactMut<'data, T> {
new(chunk_size: usize, slice: &'data mut [T]) -> Self280     pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {
281         let rem_len = slice.len() % chunk_size;
282         let (rem, slice) = slice.split_at_mut(rem_len);
283         Self {
284             chunk_size,
285             slice,
286             rem,
287         }
288     }
289 
290     /// Return the remainder of the original slice that is not going to be
291     /// returned by the iterator. The returned slice has at most `chunk_size-1`
292     /// elements.
293     ///
294     /// Note that this has to consume `self` to return the original lifetime of
295     /// the data, which prevents this from actually being used as a parallel
296     /// iterator since that also consumes. This method is provided for parity
297     /// with `std::iter::RChunksExactMut`, but consider calling `remainder()` or
298     /// `take_remainder()` as alternatives.
into_remainder(self) -> &'data mut [T]299     pub fn into_remainder(self) -> &'data mut [T] {
300         self.rem
301     }
302 
303     /// Return the remainder of the original slice that is not going to be
304     /// returned by the iterator. The returned slice has at most `chunk_size-1`
305     /// elements.
306     ///
307     /// Consider `take_remainder()` if you need access to the data with its
308     /// original lifetime, rather than borrowing through `&mut self` here.
remainder(&mut self) -> &mut [T]309     pub fn remainder(&mut self) -> &mut [T] {
310         self.rem
311     }
312 
313     /// Return the remainder of the original slice that is not going to be
314     /// returned by the iterator. The returned slice has at most `chunk_size-1`
315     /// elements. Subsequent calls will return an empty slice.
take_remainder(&mut self) -> &'data mut [T]316     pub fn take_remainder(&mut self) -> &'data mut [T] {
317         std::mem::take(&mut self.rem)
318     }
319 }
320 
321 impl<'data, T: Send + 'data> ParallelIterator for RChunksExactMut<'data, T> {
322     type Item = &'data mut [T];
323 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,324     fn drive_unindexed<C>(self, consumer: C) -> C::Result
325     where
326         C: UnindexedConsumer<Self::Item>,
327     {
328         bridge(self, consumer)
329     }
330 
opt_len(&self) -> Option<usize>331     fn opt_len(&self) -> Option<usize> {
332         Some(self.len())
333     }
334 }
335 
336 impl<'data, T: Send + 'data> IndexedParallelIterator for RChunksExactMut<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,337     fn drive<C>(self, consumer: C) -> C::Result
338     where
339         C: Consumer<Self::Item>,
340     {
341         bridge(self, consumer)
342     }
343 
len(&self) -> usize344     fn len(&self) -> usize {
345         self.slice.len() / self.chunk_size
346     }
347 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,348     fn with_producer<CB>(self, callback: CB) -> CB::Output
349     where
350         CB: ProducerCallback<Self::Item>,
351     {
352         callback.callback(RChunksExactMutProducer {
353             chunk_size: self.chunk_size,
354             slice: self.slice,
355         })
356     }
357 }
358 
359 struct RChunksExactMutProducer<'data, T: Send> {
360     chunk_size: usize,
361     slice: &'data mut [T],
362 }
363 
364 impl<'data, T: 'data + Send> Producer for RChunksExactMutProducer<'data, T> {
365     type Item = &'data mut [T];
366     type IntoIter = ::std::slice::RChunksExactMut<'data, T>;
367 
into_iter(self) -> Self::IntoIter368     fn into_iter(self) -> Self::IntoIter {
369         self.slice.rchunks_exact_mut(self.chunk_size)
370     }
371 
split_at(self, index: usize) -> (Self, Self)372     fn split_at(self, index: usize) -> (Self, Self) {
373         let elem_index = self.slice.len() - index * self.chunk_size;
374         let (left, right) = self.slice.split_at_mut(elem_index);
375         (
376             RChunksExactMutProducer {
377                 chunk_size: self.chunk_size,
378                 slice: right,
379             },
380             RChunksExactMutProducer {
381                 chunk_size: self.chunk_size,
382                 slice: left,
383             },
384         )
385     }
386 }
387