rayon/slice/
windows.rs

1use crate::iter::plumbing::*;
2use crate::iter::*;
3
4/// Parallel iterator over immutable overlapping windows of a slice
5#[derive(Debug)]
6pub struct Windows<'data, T> {
7    window_size: usize,
8    slice: &'data [T],
9}
10
11impl<'data, T> Windows<'data, T> {
12    pub(super) fn new(window_size: usize, slice: &'data [T]) -> Self {
13        Self { window_size, slice }
14    }
15}
16
17impl<T> Clone for Windows<'_, T> {
18    fn clone(&self) -> Self {
19        Windows { ..*self }
20    }
21}
22
23impl<'data, T: Sync> ParallelIterator for Windows<'data, T> {
24    type Item = &'data [T];
25
26    fn drive_unindexed<C>(self, consumer: C) -> C::Result
27    where
28        C: UnindexedConsumer<Self::Item>,
29    {
30        bridge(self, consumer)
31    }
32
33    fn opt_len(&self) -> Option<usize> {
34        Some(self.len())
35    }
36}
37
38impl<T: Sync> IndexedParallelIterator for Windows<'_, T> {
39    fn drive<C>(self, consumer: C) -> C::Result
40    where
41        C: Consumer<Self::Item>,
42    {
43        bridge(self, consumer)
44    }
45
46    fn len(&self) -> usize {
47        assert!(self.window_size >= 1);
48        self.slice.len().saturating_sub(self.window_size - 1)
49    }
50
51    fn with_producer<CB>(self, callback: CB) -> CB::Output
52    where
53        CB: ProducerCallback<Self::Item>,
54    {
55        callback.callback(WindowsProducer {
56            window_size: self.window_size,
57            slice: self.slice,
58        })
59    }
60}
61
62struct WindowsProducer<'data, T: Sync> {
63    window_size: usize,
64    slice: &'data [T],
65}
66
67impl<'data, T: Sync> Producer for WindowsProducer<'data, T> {
68    type Item = &'data [T];
69    type IntoIter = ::std::slice::Windows<'data, T>;
70
71    fn into_iter(self) -> Self::IntoIter {
72        self.slice.windows(self.window_size)
73    }
74
75    fn split_at(self, index: usize) -> (Self, Self) {
76        let left_index = Ord::min(self.slice.len(), index + (self.window_size - 1));
77        let left = &self.slice[..left_index];
78        let right = &self.slice[index..];
79        (
80            WindowsProducer {
81                window_size: self.window_size,
82                slice: left,
83            },
84            WindowsProducer {
85                window_size: self.window_size,
86                slice: right,
87            },
88        )
89    }
90}
91
92/// Parallel iterator over immutable overlapping windows of a slice
93#[derive(Debug)]
94pub struct ArrayWindows<'data, T: Sync, const N: usize> {
95    slice: &'data [T],
96}
97
98impl<'data, T: Sync, const N: usize> ArrayWindows<'data, T, N> {
99    pub(super) fn new(slice: &'data [T]) -> Self {
100        ArrayWindows { slice }
101    }
102}
103
104impl<T: Sync, const N: usize> Clone for ArrayWindows<'_, T, N> {
105    fn clone(&self) -> Self {
106        ArrayWindows { ..*self }
107    }
108}
109
110impl<'data, T: Sync, const N: usize> ParallelIterator for ArrayWindows<'data, T, N> {
111    type Item = &'data [T; N];
112
113    fn drive_unindexed<C>(self, consumer: C) -> C::Result
114    where
115        C: UnindexedConsumer<Self::Item>,
116    {
117        bridge(self, consumer)
118    }
119
120    fn opt_len(&self) -> Option<usize> {
121        Some(self.len())
122    }
123}
124
125impl<T: Sync, const N: usize> IndexedParallelIterator for ArrayWindows<'_, T, N> {
126    fn drive<C>(self, consumer: C) -> C::Result
127    where
128        C: Consumer<Self::Item>,
129    {
130        bridge(self, consumer)
131    }
132
133    fn len(&self) -> usize {
134        assert!(N >= 1);
135        self.slice.len().saturating_sub(const { N - 1 })
136    }
137
138    fn with_producer<CB>(self, callback: CB) -> CB::Output
139    where
140        CB: ProducerCallback<Self::Item>,
141    {
142        // TODO (MSRV 1.94): use our own producer and the standard `array_windows`
143        Windows::new(N, self.slice)
144            .map(|slice| slice.try_into().unwrap())
145            .with_producer(callback)
146    }
147}