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