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> { |
14 | 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> { |
20 | 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 | |
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 | |
40 | impl<'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 | |
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 | |
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)] |
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> { |
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 | |
120 | impl<'data, T: Sync> Clone for ChunksExact<'data, T> { |
121 | 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 | |
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 | |
141 | impl<'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 | |
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 | |
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)] |
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> { |
201 | 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 | |
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 | |
221 | impl<'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 | |
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 | |
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)] |
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> { |
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 | |
324 | impl<'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 | |
339 | impl<'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 | |
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 | |
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 | |