1 use crate::iter::plumbing::*;
2 use crate::iter::*;
3 use crate::math::div_round_up;
4 use std::cmp;
5 
6 /// Parallel iterator over immutable non-overlapping chunks of a slice
7 #[derive(Debug)]
8 pub struct Chunks<'data, T: Sync> {
9     chunk_size: usize,
10     slice: &'data [T],
11 }
12 
13 impl<'data, T: Sync> Chunks<'data, T> {
new(chunk_size: usize, slice: &'data [T]) -> Self14     pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
15         Self { chunk_size, slice }
16     }
17 }
18 
19 impl<'data, T: Sync> Clone for Chunks<'data, T> {
clone(&self) -> Self20     fn clone(&self) -> Self {
21         Chunks { ..*self }
22     }
23 }
24 
25 impl<'data, T: Sync + 'data> ParallelIterator for Chunks<'data, T> {
26     type Item = &'data [T];
27 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,28     fn drive_unindexed<C>(self, consumer: C) -> C::Result
29     where
30         C: UnindexedConsumer<Self::Item>,
31     {
32         bridge(self, consumer)
33     }
34 
opt_len(&self) -> Option<usize>35     fn opt_len(&self) -> Option<usize> {
36         Some(self.len())
37     }
38 }
39 
40 impl<'data, T: Sync + 'data> IndexedParallelIterator for Chunks<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,41     fn drive<C>(self, consumer: C) -> C::Result
42     where
43         C: Consumer<Self::Item>,
44     {
45         bridge(self, consumer)
46     }
47 
len(&self) -> usize48     fn len(&self) -> usize {
49         div_round_up(self.slice.len(), self.chunk_size)
50     }
51 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,52     fn with_producer<CB>(self, callback: CB) -> CB::Output
53     where
54         CB: ProducerCallback<Self::Item>,
55     {
56         callback.callback(ChunksProducer {
57             chunk_size: self.chunk_size,
58             slice: self.slice,
59         })
60     }
61 }
62 
63 struct ChunksProducer<'data, T: Sync> {
64     chunk_size: usize,
65     slice: &'data [T],
66 }
67 
68 impl<'data, T: 'data + Sync> Producer for ChunksProducer<'data, T> {
69     type Item = &'data [T];
70     type IntoIter = ::std::slice::Chunks<'data, T>;
71 
into_iter(self) -> Self::IntoIter72     fn into_iter(self) -> Self::IntoIter {
73         self.slice.chunks(self.chunk_size)
74     }
75 
split_at(self, index: usize) -> (Self, Self)76     fn split_at(self, index: usize) -> (Self, Self) {
77         let elem_index = cmp::min(index * self.chunk_size, self.slice.len());
78         let (left, right) = self.slice.split_at(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)]
94 pub struct ChunksExact<'data, T: Sync> {
95     chunk_size: usize,
96     slice: &'data [T],
97     rem: &'data [T],
98 }
99 
100 impl<'data, T: Sync> ChunksExact<'data, T> {
new(chunk_size: usize, slice: &'data [T]) -> Self101     pub(super) fn new(chunk_size: usize, slice: &'data [T]) -> Self {
102         let rem_len = slice.len() % chunk_size;
103         let len = slice.len() - rem_len;
104         let (slice, rem) = slice.split_at(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.
remainder(&self) -> &'data [T]115     pub fn remainder(&self) -> &'data [T] {
116         self.rem
117     }
118 }
119 
120 impl<'data, T: Sync> Clone for ChunksExact<'data, T> {
clone(&self) -> Self121     fn clone(&self) -> Self {
122         ChunksExact { ..*self }
123     }
124 }
125 
126 impl<'data, T: Sync + 'data> ParallelIterator for ChunksExact<'data, T> {
127     type Item = &'data [T];
128 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,129     fn drive_unindexed<C>(self, consumer: C) -> C::Result
130     where
131         C: UnindexedConsumer<Self::Item>,
132     {
133         bridge(self, consumer)
134     }
135 
opt_len(&self) -> Option<usize>136     fn opt_len(&self) -> Option<usize> {
137         Some(self.len())
138     }
139 }
140 
141 impl<'data, T: Sync + 'data> IndexedParallelIterator for ChunksExact<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,142     fn drive<C>(self, consumer: C) -> C::Result
143     where
144         C: Consumer<Self::Item>,
145     {
146         bridge(self, consumer)
147     }
148 
len(&self) -> usize149     fn len(&self) -> usize {
150         self.slice.len() / self.chunk_size
151     }
152 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,153     fn with_producer<CB>(self, callback: CB) -> CB::Output
154     where
155         CB: ProducerCallback<Self::Item>,
156     {
157         callback.callback(ChunksExactProducer {
158             chunk_size: self.chunk_size,
159             slice: self.slice,
160         })
161     }
162 }
163 
164 struct ChunksExactProducer<'data, T: Sync> {
165     chunk_size: usize,
166     slice: &'data [T],
167 }
168 
169 impl<'data, T: 'data + Sync> Producer for ChunksExactProducer<'data, T> {
170     type Item = &'data [T];
171     type IntoIter = ::std::slice::ChunksExact<'data, T>;
172 
into_iter(self) -> Self::IntoIter173     fn into_iter(self) -> Self::IntoIter {
174         self.slice.chunks_exact(self.chunk_size)
175     }
176 
split_at(self, index: usize) -> (Self, Self)177     fn split_at(self, index: usize) -> (Self, Self) {
178         let elem_index = index * self.chunk_size;
179         let (left, right) = self.slice.split_at(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)]
195 pub struct ChunksMut<'data, T: Send> {
196     chunk_size: usize,
197     slice: &'data mut [T],
198 }
199 
200 impl<'data, T: Send> ChunksMut<'data, T> {
new(chunk_size: usize, slice: &'data mut [T]) -> Self201     pub(super) fn new(chunk_size: usize, slice: &'data mut [T]) -> Self {
202         Self { chunk_size, slice }
203     }
204 }
205 
206 impl<'data, T: Send + 'data> ParallelIterator for ChunksMut<'data, T> {
207     type Item = &'data mut [T];
208 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,209     fn drive_unindexed<C>(self, consumer: C) -> C::Result
210     where
211         C: UnindexedConsumer<Self::Item>,
212     {
213         bridge(self, consumer)
214     }
215 
opt_len(&self) -> Option<usize>216     fn opt_len(&self) -> Option<usize> {
217         Some(self.len())
218     }
219 }
220 
221 impl<'data, T: Send + 'data> IndexedParallelIterator for ChunksMut<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,222     fn drive<C>(self, consumer: C) -> C::Result
223     where
224         C: Consumer<Self::Item>,
225     {
226         bridge(self, consumer)
227     }
228 
len(&self) -> usize229     fn len(&self) -> usize {
230         div_round_up(self.slice.len(), self.chunk_size)
231     }
232 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,233     fn with_producer<CB>(self, callback: CB) -> CB::Output
234     where
235         CB: ProducerCallback<Self::Item>,
236     {
237         callback.callback(ChunksMutProducer {
238             chunk_size: self.chunk_size,
239             slice: self.slice,
240         })
241     }
242 }
243 
244 struct ChunksMutProducer<'data, T: Send> {
245     chunk_size: usize,
246     slice: &'data mut [T],
247 }
248 
249 impl<'data, T: 'data + Send> Producer for ChunksMutProducer<'data, T> {
250     type Item = &'data mut [T];
251     type IntoIter = ::std::slice::ChunksMut<'data, T>;
252 
into_iter(self) -> Self::IntoIter253     fn into_iter(self) -> Self::IntoIter {
254         self.slice.chunks_mut(self.chunk_size)
255     }
256 
split_at(self, index: usize) -> (Self, Self)257     fn split_at(self, index: usize) -> (Self, Self) {
258         let elem_index = cmp::min(index * self.chunk_size, self.slice.len());
259         let (left, right) = self.slice.split_at_mut(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)]
275 pub struct ChunksExactMut<'data, T: Send> {
276     chunk_size: usize,
277     slice: &'data mut [T],
278     rem: &'data mut [T],
279 }
280 
281 impl<'data, T: Send> ChunksExactMut<'data, T> {
new(chunk_size: usize, slice: &'data mut [T]) -> Self282     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.
into_remainder(self) -> &'data mut [T]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.
remainder(&mut self) -> &mut [T]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.
take_remainder(&mut self) -> &'data mut [T]319     pub fn take_remainder(&mut self) -> &'data mut [T] {
320         std::mem::take(&mut self.rem)
321     }
322 }
323 
324 impl<'data, T: Send + 'data> ParallelIterator for ChunksExactMut<'data, T> {
325     type Item = &'data mut [T];
326 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,327     fn drive_unindexed<C>(self, consumer: C) -> C::Result
328     where
329         C: UnindexedConsumer<Self::Item>,
330     {
331         bridge(self, consumer)
332     }
333 
opt_len(&self) -> Option<usize>334     fn opt_len(&self) -> Option<usize> {
335         Some(self.len())
336     }
337 }
338 
339 impl<'data, T: Send + 'data> IndexedParallelIterator for ChunksExactMut<'data, T> {
drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,340     fn drive<C>(self, consumer: C) -> C::Result
341     where
342         C: Consumer<Self::Item>,
343     {
344         bridge(self, consumer)
345     }
346 
len(&self) -> usize347     fn len(&self) -> usize {
348         self.slice.len() / self.chunk_size
349     }
350 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,351     fn with_producer<CB>(self, callback: CB) -> CB::Output
352     where
353         CB: ProducerCallback<Self::Item>,
354     {
355         callback.callback(ChunksExactMutProducer {
356             chunk_size: self.chunk_size,
357             slice: self.slice,
358         })
359     }
360 }
361 
362 struct ChunksExactMutProducer<'data, T: Send> {
363     chunk_size: usize,
364     slice: &'data mut [T],
365 }
366 
367 impl<'data, T: 'data + Send> Producer for ChunksExactMutProducer<'data, T> {
368     type Item = &'data mut [T];
369     type IntoIter = ::std::slice::ChunksExactMut<'data, T>;
370 
into_iter(self) -> Self::IntoIter371     fn into_iter(self) -> Self::IntoIter {
372         self.slice.chunks_exact_mut(self.chunk_size)
373     }
374 
split_at(self, index: usize) -> (Self, Self)375     fn split_at(self, index: usize) -> (Self, Self) {
376         let elem_index = index * self.chunk_size;
377         let (left, right) = self.slice.split_at_mut(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