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