rayon/slice/
rchunks.rs

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