1use bit_vec::BitVec;
50use std::ops::{Range, RangeInclusive};
51
52enum State {
53 Start,
54 End,
55 Lattice,
56 Finished,
57}
58
59pub struct RlpIter {
60 tested: BitVec,
61 shift: usize,
62 range: usize,
63 numerator: usize,
64 pow: usize,
65 final_pow: usize,
66 state: State,
67}
68
69fn ilog2(i: usize) -> usize {
74 (i as f64).log2().round() as usize
75}
76
77impl Iterator for RlpIter {
78 type Item = usize;
79
80 fn next(&mut self) -> Option<Self::Item> {
81 let unshifted = match self.state {
82 State::Start => {
83 self.state = State::End;
84 self.tested.set(0, true);
85 Some(0)
86 }
87 State::End => {
88 if self.range == 0 {
89 self.state = State::Finished;
90 None
91 } else {
92 self.state = State::Lattice;
93 self.tested.set(self.range, true);
94 Some(self.range)
95 }
96 }
97 State::Lattice => {
98 let mut out = None;
99
100 while self.pow <= self.final_pow {
101 let denominator = (1_u64 << self.pow) as usize;
103 let val = (self.range as f64 * (self.numerator as f64 / denominator as f64))
104 .round() as usize;
105
106 if !self.tested.get(val).unwrap() {
107 out = Some(val);
108 self.tested.set(val, true);
109 }
110
111 if self.numerator == denominator - 1 {
113 self.numerator = 1;
114 self.pow += 1;
115 } else {
116 self.numerator += 1;
117 }
118
119 if out.is_some() {
120 break;
121 }
122 }
123
124 if out.is_some() {
125 out
126 } else {
127 while self.numerator <= self.range {
130 if !self.tested.get(self.numerator).unwrap() {
131 out = Some(self.numerator);
132 self.tested.set(self.numerator, true);
133 self.numerator += 1;
134 break;
135 } else {
136 self.numerator += 1;
137 }
138 }
139
140 if self.numerator > self.range {
142 self.state = State::Finished;
143 }
144
145 out
146 }
147 }
148 State::Finished => None,
149 };
150
151 unshifted.map(|v| v + self.shift)
152 }
153}
154
155pub trait RlpIterator {
156 fn rlp_iter(&self) -> RlpIter;
157}
158
159impl RlpIterator for Range<usize> {
160 fn rlp_iter(&self) -> RlpIter {
161 let range = self.end - self.start - 1;
162 RlpIter {
163 tested: BitVec::from_elem(range + 1, false),
164 shift: self.start,
165 range,
166 numerator: 1,
167 pow: 1,
168 final_pow: ilog2(range),
169 state: State::Start,
170 }
171 }
172}
173
174impl RlpIterator for RangeInclusive<usize> {
175 fn rlp_iter(&self) -> RlpIter {
176 let range = self.end() - self.start();
177 RlpIter {
178 tested: BitVec::from_elem(range + 1, false),
179 shift: *self.start(),
180 range,
181 numerator: 1,
182 pow: 1,
183 final_pow: ilog2(range),
184 state: State::Start,
185 }
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use crate::RlpIterator;
192
193 #[test]
194 fn inclusive_range_works() {
195 let out: Vec<usize> = (0..=8).rlp_iter().collect();
196 assert_eq!(out[..], [0, 8, 4, 2, 6, 1, 3, 5, 7]);
197 }
198
199 #[test]
200 fn exclusive_range_works() {
201 let out: Vec<usize> = (0..9).rlp_iter().collect();
202 assert_eq!(out[..], [0, 8, 4, 2, 6, 1, 3, 5, 7]);
203 }
204
205 #[test]
206 fn offset_works() {
207 let out: Vec<usize> = (1..=9).rlp_iter().collect();
208 assert_eq!(out[..], [1, 9, 5, 3, 7, 2, 4, 6, 8]);
209 }
210
211 #[test]
212 fn extreme_offset_inclusive_works() {
213 let out: Vec<usize> = (1_000..=1_008).rlp_iter().collect();
214 assert_eq!(
215 out[..],
216 [1_000, 1_008, 1_004, 1_002, 1_006, 1_001, 1_003, 1_005, 1_007]
217 );
218 }
219
220 #[test]
221 fn extreme_offset_exclusive_works() {
222 let out: Vec<usize> = (1_000..1_009).rlp_iter().collect();
223 assert_eq!(
224 out[..],
225 [1_000, 1_008, 1_004, 1_002, 1_006, 1_001, 1_003, 1_005, 1_007]
226 );
227 }
228
229 #[test]
230 fn output_inclusive_is_complete() {
231 let mut out: Vec<usize> = (7..=7919).rlp_iter().collect();
232 let expected: Vec<usize> = (7..=7919).into_iter().collect();
233
234 out.sort();
235 assert_eq!(expected, out);
236 }
237
238 #[test]
239 fn output_exclusive_is_complete() {
240 let mut out: Vec<usize> = (7..7919).rlp_iter().collect();
241 let expected: Vec<usize> = (7..7919).into_iter().collect();
242
243 out.sort();
244 assert_eq!(expected, out);
245 }
246
247 #[test]
248 fn test_readme_example() {
249 let out: Vec<usize> = (0..=100).rlp_iter().collect();
250
251 assert_eq!(out[0..9], [0, 100, 50, 25, 75, 13, 38, 63, 88]);
252 }
253}