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