1use super::plumbing::*;
2use super::*;
3use std::iter;
4
5#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10#[derive(Debug, Clone)]
11pub struct StepBy<I> {
12 base: I,
13 step: usize,
14}
15
16impl<I> StepBy<I> {
17 pub(super) fn new(base: I, step: usize) -> Self {
19 StepBy { base, step }
20 }
21}
22
23impl<I> ParallelIterator for StepBy<I>
24where
25 I: IndexedParallelIterator,
26{
27 type Item = I::Item;
28
29 fn drive_unindexed<C>(self, consumer: C) -> C::Result
30 where
31 C: UnindexedConsumer<Self::Item>,
32 {
33 bridge(self, consumer)
34 }
35
36 fn opt_len(&self) -> Option<usize> {
37 Some(self.len())
38 }
39}
40
41impl<I> IndexedParallelIterator for StepBy<I>
42where
43 I: IndexedParallelIterator,
44{
45 fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
46 bridge(self, consumer)
47 }
48
49 fn len(&self) -> usize {
50 self.base.len().div_ceil(self.step)
51 }
52
53 fn with_producer<CB>(self, callback: CB) -> CB::Output
54 where
55 CB: ProducerCallback<Self::Item>,
56 {
57 let len = self.base.len();
58 return self.base.with_producer(Callback {
59 callback,
60 step: self.step,
61 len,
62 });
63
64 struct Callback<CB> {
65 callback: CB,
66 step: usize,
67 len: usize,
68 }
69
70 impl<T, CB> ProducerCallback<T> for Callback<CB>
71 where
72 CB: ProducerCallback<T>,
73 {
74 type Output = CB::Output;
75 fn callback<P>(self, base: P) -> CB::Output
76 where
77 P: Producer<Item = T>,
78 {
79 let producer = StepByProducer {
80 base,
81 step: self.step,
82 len: self.len,
83 };
84 self.callback.callback(producer)
85 }
86 }
87 }
88}
89
90struct StepByProducer<P> {
94 base: P,
95 step: usize,
96 len: usize,
97}
98
99impl<P> Producer for StepByProducer<P>
100where
101 P: Producer,
102{
103 type Item = P::Item;
104 type IntoIter = iter::StepBy<P::IntoIter>;
105
106 fn into_iter(self) -> Self::IntoIter {
107 self.base.into_iter().step_by(self.step)
108 }
109
110 fn split_at(self, index: usize) -> (Self, Self) {
111 let elem_index = Ord::min(index * self.step, self.len);
112
113 let (left, right) = self.base.split_at(elem_index);
114 (
115 StepByProducer {
116 base: left,
117 step: self.step,
118 len: elem_index,
119 },
120 StepByProducer {
121 base: right,
122 step: self.step,
123 len: self.len - elem_index,
124 },
125 )
126 }
127
128 fn min_len(&self) -> usize {
129 self.base.min_len().div_ceil(self.step)
130 }
131
132 fn max_len(&self) -> usize {
133 self.base.max_len() / self.step
134 }
135}