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