1use crate::iter::plumbing::*;
2use crate::iter::*;
3use crate::math::div_round_up;
4
5/// Parallel iterator over immutable non-overlapping chunks of a slice, starting at the end.
6#[derive(Debug)]
7pub struct RChunks<'data, T: Sync> {
8 chunk_size: usize,
9 slice: &'data [T],
10}
11
12impl<'data, T: Sync> RChunks<'data, T> {
13 pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
14 Self { chunk_size, slice }
15 }
16}
17
18impl<'data, T: Sync> Clone for RChunks<'data, T> {
19 fn clone(&self) -> Self {
20 RChunks { ..*self }
21 }
22}
23
24impl<'data, T: Sync + 'data> ParallelIterator for RChunks<'data, T> {
25 type Item = &'data [T];
26
27 fn drive_unindexed<C>(self, consumer: C) -> C::Result
28 where
29 C: UnindexedConsumer<Self::Item>,
30 {
31 bridge(self, consumer)
32 }
33
34 fn opt_len(&self) -> Option<usize> {
35 Some(self.len())
36 }
37}
38
39impl<'data, T: Sync + 'data> IndexedParallelIterator for RChunks<'data, T> {
40 fn drive<C>(self, consumer: C) -> C::Result
41 where
42 C: Consumer<Self::Item>,
43 {
44 bridge(self, consumer)
45 }
46
47 fn len(&self) -> usize {
48 div_round_up(self.slice.len(), self.chunk_size)
49 }
50
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
62struct RChunksProducer<'data, T: Sync> {
63 chunk_size: usize,
64 slice: &'data [T],
65}
66
67impl<'data, T: 'data + Sync> Producer for RChunksProducer<'data, T> {
68 type Item = &'data [T];
69 type IntoIter = ::std::slice::RChunks<'data, T>;
70
71 fn into_iter(self) -> Self::IntoIter {
72 self.slice.rchunks(self.chunk_size)
73 }
74
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)]
93pub struct RChunksExact<'data, T: Sync> {
94 chunk_size: usize,
95 slice: &'data [T],
96 rem: &'data [T],
97}
98
99impl<'data, T: Sync> RChunksExact<'data, T> {
100 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.
113 pub fn remainder(&self) -> &'data [T] {
114 self.rem
115 }
116}
117
118impl<'data, T: Sync> Clone for RChunksExact<'data, T> {
119 fn clone(&self) -> Self {
120 RChunksExact { ..*self }
121 }
122}
123
124impl<'data, T: Sync + 'data> ParallelIterator for RChunksExact<'data, T> {
125 type Item = &'data [T];
126
127 fn drive_unindexed<C>(self, consumer: C) -> C::Result
128 where
129 C: UnindexedConsumer<Self::Item>,
130 {
131 bridge(self, consumer)
132 }
133
134 fn opt_len(&self) -> Option<usize> {
135 Some(self.len())
136 }
137}
138
139impl<'data, T: Sync + 'data> IndexedParallelIterator for RChunksExact<'data, T> {
140 fn drive<C>(self, consumer: C) -> C::Result
141 where
142 C: Consumer<Self::Item>,
143 {
144 bridge(self, consumer)
145 }
146
147 fn len(&self) -> usize {
148 self.slice.len() / self.chunk_size
149 }
150
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
162struct RChunksExactProducer<'data, T: Sync> {
163 chunk_size: usize,
164 slice: &'data [T],
165}
166
167impl<'data, T: 'data + Sync> Producer for RChunksExactProducer<'data, T> {
168 type Item = &'data [T];
169 type IntoIter = ::std::slice::RChunksExact<'data, T>;
170
171 fn into_iter(self) -> Self::IntoIter {
172 self.slice.rchunks_exact(self.chunk_size)
173 }
174
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)]
193pub struct RChunksMut<'data, T: Send> {
194 chunk_size: usize,
195 slice: &'data mut [T],
196}
197
198impl<'data, T: Send> RChunksMut<'data, T> {
199 pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {
200 Self { chunk_size, slice }
201 }
202}
203
204impl<'data, T: Send + 'data> ParallelIterator for RChunksMut<'data, T> {
205 type Item = &'data mut [T];
206
207 fn drive_unindexed<C>(self, consumer: C) -> C::Result
208 where
209 C: UnindexedConsumer<Self::Item>,
210 {
211 bridge(self, consumer)
212 }
213
214 fn opt_len(&self) -> Option<usize> {
215 Some(self.len())
216 }
217}
218
219impl<'data, T: Send + 'data> IndexedParallelIterator for RChunksMut<'data, T> {
220 fn drive<C>(self, consumer: C) -> C::Result
221 where
222 C: Consumer<Self::Item>,
223 {
224 bridge(self, consumer)
225 }
226
227 fn len(&self) -> usize {
228 div_round_up(self.slice.len(), self.chunk_size)
229 }
230
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
242struct RChunksMutProducer<'data, T: Send> {
243 chunk_size: usize,
244 slice: &'data mut [T],
245}
246
247impl<'data, T: 'data + Send> Producer for RChunksMutProducer<'data, T> {
248 type Item = &'data mut [T];
249 type IntoIter = ::std::slice::RChunksMut<'data, T>;
250
251 fn into_iter(self) -> Self::IntoIter {
252 self.slice.rchunks_mut(self.chunk_size)
253 }
254
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)]
273pub struct RChunksExactMut<'data, T: Send> {
274 chunk_size: usize,
275 slice: &'data mut [T],
276 rem: &'data mut [T],
277}
278
279impl<'data, T: Send> RChunksExactMut<'data, T> {
280 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.
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.
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.
316 pub fn take_remainder(&mut self) -> &'data mut [T] {
317 std::mem::take(&mut self.rem)
318 }
319}
320
321impl<'data, T: Send + 'data> ParallelIterator for RChunksExactMut<'data, T> {
322 type Item = &'data mut [T];
323
324 fn drive_unindexed<C>(self, consumer: C) -> C::Result
325 where
326 C: UnindexedConsumer<Self::Item>,
327 {
328 bridge(self, consumer)
329 }
330
331 fn opt_len(&self) -> Option<usize> {
332 Some(self.len())
333 }
334}
335
336impl<'data, T: Send + 'data> IndexedParallelIterator for RChunksExactMut<'data, T> {
337 fn drive<C>(self, consumer: C) -> C::Result
338 where
339 C: Consumer<Self::Item>,
340 {
341 bridge(self, consumer)
342 }
343
344 fn len(&self) -> usize {
345 self.slice.len() / self.chunk_size
346 }
347
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
359struct RChunksExactMutProducer<'data, T: Send> {
360 chunk_size: usize,
361 slice: &'data mut [T],
362}
363
364impl<'data, T: 'data + Send> Producer for RChunksExactMutProducer<'data, T> {
365 type Item = &'data mut [T];
366 type IntoIter = ::std::slice::RChunksExactMut<'data, T>;
367
368 fn into_iter(self) -> Self::IntoIter {
369 self.slice.rchunks_exact_mut(self.chunk_size)
370 }
371
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