1 #![cfg(step_by)]
2 use std::cmp::min;
3 
4 use super::plumbing::*;
5 use super::*;
6 use crate::math::div_round_up;
7 use std::iter;
8 use std::usize;
9 
10 /// `StepBy` is an iterator that skips `n` elements between each yield, where `n` is the given step.
11 /// This struct is created by the [`step_by()`] method on [`IndexedParallelIterator`]
12 ///
13 /// [`step_by()`]: trait.IndexedParallelIterator.html#method.step_by
14 /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html
15 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
16 #[derive(Debug, Clone)]
17 pub struct StepBy<I: IndexedParallelIterator> {
18     base: I,
19     step: usize,
20 }
21 
22 impl<I> StepBy<I>
23 where
24     I: IndexedParallelIterator,
25 {
26     /// Creates a new `StepBy` iterator.
new(base: I, step: usize) -> Self27     pub(super) fn new(base: I, step: usize) -> Self {
28         StepBy { base, step }
29     }
30 }
31 
32 impl<I> ParallelIterator for StepBy<I>
33 where
34     I: IndexedParallelIterator,
35 {
36     type Item = I::Item;
37 
drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,38     fn drive_unindexed<C>(self, consumer: C) -> C::Result
39     where
40         C: UnindexedConsumer<Self::Item>,
41     {
42         bridge(self, consumer)
43     }
44 
opt_len(&self) -> Option<usize>45     fn opt_len(&self) -> Option<usize> {
46         Some(self.len())
47     }
48 }
49 
50 impl<I> IndexedParallelIterator for StepBy<I>
51 where
52     I: IndexedParallelIterator,
53 {
drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result54     fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result {
55         bridge(self, consumer)
56     }
57 
len(&self) -> usize58     fn len(&self) -> usize {
59         div_round_up(self.base.len(), self.step)
60     }
61 
with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,62     fn with_producer<CB>(self, callback: CB) -> CB::Output
63     where
64         CB: ProducerCallback<Self::Item>,
65     {
66         let len = self.base.len();
67         return self.base.with_producer(Callback {
68             callback,
69             step: self.step,
70             len,
71         });
72 
73         struct Callback<CB> {
74             callback: CB,
75             step: usize,
76             len: usize,
77         }
78 
79         impl<T, CB> ProducerCallback<T> for Callback<CB>
80         where
81             CB: ProducerCallback<T>,
82         {
83             type Output = CB::Output;
84             fn callback<P>(self, base: P) -> CB::Output
85             where
86                 P: Producer<Item = T>,
87             {
88                 let producer = StepByProducer {
89                     base,
90                     step: self.step,
91                     len: self.len,
92                 };
93                 self.callback.callback(producer)
94             }
95         }
96     }
97 }
98 
99 /// ////////////////////////////////////////////////////////////////////////
100 /// Producer implementation
101 
102 struct StepByProducer<P> {
103     base: P,
104     step: usize,
105     len: usize,
106 }
107 
108 impl<P> Producer for StepByProducer<P>
109 where
110     P: Producer,
111 {
112     type Item = P::Item;
113     type IntoIter = iter::StepBy<P::IntoIter>;
114 
into_iter(self) -> Self::IntoIter115     fn into_iter(self) -> Self::IntoIter {
116         self.base.into_iter().step_by(self.step)
117     }
118 
split_at(self, index: usize) -> (Self, Self)119     fn split_at(self, index: usize) -> (Self, Self) {
120         let elem_index = min(index * self.step, self.len);
121 
122         let (left, right) = self.base.split_at(elem_index);
123         (
124             StepByProducer {
125                 base: left,
126                 step: self.step,
127                 len: elem_index,
128             },
129             StepByProducer {
130                 base: right,
131                 step: self.step,
132                 len: self.len - elem_index,
133             },
134         )
135     }
136 
min_len(&self) -> usize137     fn min_len(&self) -> usize {
138         div_round_up(self.base.min_len(), self.step)
139     }
140 
max_len(&self) -> usize141     fn max_len(&self) -> usize {
142         self.base.max_len() / self.step
143     }
144 }
145