|
3 | 3 | use crate::iter::plumbing::*; |
4 | 4 | use crate::iter::*; |
5 | 5 |
|
6 | | -use super::{Iter, IterMut}; |
| 6 | +use super::{Iter, IterMut, ParallelSlice}; |
7 | 7 |
|
8 | 8 | /// Parallel iterator over immutable non-overlapping chunks of a slice |
9 | 9 | #[derive(Debug)] |
@@ -172,3 +172,67 @@ impl<'data, T: Send + 'data, const N: usize> IndexedParallelIterator |
172 | 172 | self.iter.with_producer(callback) |
173 | 173 | } |
174 | 174 | } |
| 175 | + |
| 176 | +/// Parallel iterator over immutable overlapping windows of a slice |
| 177 | +#[derive(Debug)] |
| 178 | +pub struct ArrayWindows<'data, T: Sync, const N: usize> { |
| 179 | + slice: &'data [T], |
| 180 | +} |
| 181 | + |
| 182 | +impl<'data, T: Sync, const N: usize> ArrayWindows<'data, T, N> { |
| 183 | + pub(super) fn new(slice: &'data [T]) -> Self { |
| 184 | + ArrayWindows { slice } |
| 185 | + } |
| 186 | +} |
| 187 | + |
| 188 | +impl<'data, T: Sync, const N: usize> Clone for ArrayWindows<'data, T, N> { |
| 189 | + fn clone(&self) -> Self { |
| 190 | + ArrayWindows { ..*self } |
| 191 | + } |
| 192 | +} |
| 193 | + |
| 194 | +impl<'data, T: Sync + 'data, const N: usize> ParallelIterator for ArrayWindows<'data, T, N> { |
| 195 | + type Item = &'data [T; N]; |
| 196 | + |
| 197 | + fn drive_unindexed<C>(self, consumer: C) -> C::Result |
| 198 | + where |
| 199 | + C: UnindexedConsumer<Self::Item>, |
| 200 | + { |
| 201 | + bridge(self, consumer) |
| 202 | + } |
| 203 | + |
| 204 | + fn opt_len(&self) -> Option<usize> { |
| 205 | + Some(self.len()) |
| 206 | + } |
| 207 | +} |
| 208 | + |
| 209 | +impl<'data, T: Sync + 'data, const N: usize> IndexedParallelIterator for ArrayWindows<'data, T, N> { |
| 210 | + fn drive<C>(self, consumer: C) -> C::Result |
| 211 | + where |
| 212 | + C: Consumer<Self::Item>, |
| 213 | + { |
| 214 | + bridge(self, consumer) |
| 215 | + } |
| 216 | + |
| 217 | + fn len(&self) -> usize { |
| 218 | + assert!(N >= 1); |
| 219 | + self.slice.len().saturating_sub(N - 1) |
| 220 | + } |
| 221 | + |
| 222 | + fn with_producer<CB>(self, callback: CB) -> CB::Output |
| 223 | + where |
| 224 | + CB: ProducerCallback<Self::Item>, |
| 225 | + { |
| 226 | + fn array<T, const N: usize>(slice: &[T]) -> &[T; N] { |
| 227 | + debug_assert_eq!(slice.len(), N); |
| 228 | + let ptr = slice.as_ptr() as *const [T; N]; |
| 229 | + unsafe { &*ptr } |
| 230 | + } |
| 231 | + |
| 232 | + // FIXME: use our own producer and the standard `array_windows`, rust-lang/rust#75027 |
| 233 | + self.slice |
| 234 | + .par_windows(N) |
| 235 | + .map(array::<T, N>) |
| 236 | + .with_producer(callback) |
| 237 | + } |
| 238 | +} |
0 commit comments