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