par_iter/slice/
rchunks.rs

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