1use std::iter::FusedIterator;
73
74#[cfg(feature = "derive")]
75pub use stable_step_derive::Step;
76
77pub trait Step: PartialOrd {
79 const MIN: Self;
81
82 const MAX: Self;
84
85 fn next(&self) -> Option<Self>
87 where
88 Self: Sized;
89
90 fn prev(&self) -> Option<Self>
92 where
93 Self: Sized;
94}
95
96pub trait StepExt: Step {
98 fn iter() -> RangeIter<Self>
100 where
101 Self: Sized,
102 {
103 range(None, None)
104 }
105
106 fn iter_to(self, to: Self) -> RangeIter<Self>
108 where
109 Self: Sized,
110 {
111 range(Some(self), Some(to))
112 }
113
114 fn iter_to_inclusive(self, to: Self) -> RangeIter<Self>
116 where
117 Self: Sized,
118 {
119 range_inclusive(Some(self), Some(to))
120 }
121}
122
123impl<S> StepExt for S where S: Step {}
124
125pub struct RangeIter<S> {
127 lower: Option<S>,
128 upper: Option<S>,
129}
130
131pub fn range_inclusive<S: Step>(from: Option<S>, to: Option<S>) -> RangeIter<S> {
133 let from = match from {
134 Some(lower) => lower,
135 None => S::MIN,
136 };
137
138 let to = match to {
139 Some(upper) => upper,
140 None => S::MAX,
141 };
142
143 RangeIter {
144 lower: Some(from),
145 upper: Some(to),
146 }
147}
148
149pub fn range<S: Step>(from: Option<S>, to: Option<S>) -> RangeIter<S> {
151 let to = to.and_then(|to| to.prev());
152
153 range_inclusive(from, to)
154}
155
156impl<S> Iterator for RangeIter<S>
157where
158 S: Step,
159{
160 type Item = S;
161
162 fn next(&mut self) -> Option<Self::Item> {
163 let current = self.lower.take()?;
164
165 let upper = self.upper.as_ref()?;
166
167 if ¤t > upper {
168 return None;
169 }
170
171 self.lower = current.next();
172
173 Some(current)
174 }
175}
176
177impl<S> DoubleEndedIterator for RangeIter<S>
178where
179 S: Step,
180{
181 fn next_back(&mut self) -> Option<Self::Item> {
182 let current = self.upper.take()?;
183
184 let lower = self.lower.as_ref()?;
185
186 if ¤t < lower {
187 return None;
188 }
189
190 self.upper = current.prev();
191
192 Some(current)
193 }
194}
195
196impl<S> FusedIterator for RangeIter<S> where S: Step {}
197
198#[cfg(test)]
199mod tests {
200 use super::{range, range_inclusive, Step};
201
202 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
203 enum Test {
204 One,
205 Two,
206 Three,
207 Four,
208 }
209
210 impl Step for Test {
211 const MIN: Self = Self::One;
212 const MAX: Self = Self::Four;
213
214 fn next(&self) -> Option<Self>
215 where
216 Self: Sized,
217 {
218 match self {
219 Self::One => Some(Self::Two),
220 Self::Two => Some(Self::Three),
221 Self::Three => Some(Self::Four),
222 Self::Four => None,
223 }
224 }
225
226 fn prev(&self) -> Option<Self>
227 where
228 Self: Sized,
229 {
230 match self {
231 Self::One => None,
232 Self::Two => Some(Self::One),
233 Self::Three => Some(Self::Two),
234 Self::Four => Some(Self::Three),
235 }
236 }
237 }
238
239 #[test]
240 fn range_none_none() {
241 let v: Vec<Test> = range(None, None).collect();
242
243 assert_eq!(v, vec![Test::One, Test::Two, Test::Three, Test::Four]);
244 }
245
246 #[test]
247 fn range_reverse_none_none() {
248 let v: Vec<Test> = range(None, None).rev().collect();
249
250 assert_eq!(v, vec![Test::Four, Test::Three, Test::Two, Test::One]);
251 }
252
253 #[test]
254 fn range_upper() {
255 let v: Vec<Test> = range(None, Some(Test::Four)).collect();
256
257 assert_eq!(v, vec![Test::One, Test::Two, Test::Three]);
258 }
259
260 #[test]
261 fn range_reverse_upper() {
262 let v: Vec<Test> = range(None, Some(Test::Four)).rev().collect();
263
264 assert_eq!(v, vec![Test::Three, Test::Two, Test::One]);
265 }
266
267 #[test]
268 fn range_lower() {
269 let v: Vec<Test> = range(Some(Test::Two), None).collect();
270
271 assert_eq!(v, vec![Test::Two, Test::Three, Test::Four]);
272 }
273
274 #[test]
275 fn range_reverse_lower() {
276 let v: Vec<Test> = range(Some(Test::Two), None).rev().collect();
277
278 assert_eq!(v, vec![Test::Four, Test::Three, Test::Two]);
279 }
280
281 #[test]
282 fn range_upper_lower() {
283 let v: Vec<Test> = range(Some(Test::Two), Some(Test::Four)).collect();
284
285 assert_eq!(v, vec![Test::Two, Test::Three]);
286 }
287
288 #[test]
289 fn range_reverse_upper_lower() {
290 let v: Vec<Test> = range(Some(Test::Two), Some(Test::Four)).rev().collect();
291
292 assert_eq!(v, vec![Test::Three, Test::Two]);
293 }
294
295 #[test]
296 fn range_inclusive_none_none() {
297 let v: Vec<Test> = range_inclusive(None, None).collect();
298
299 assert_eq!(v, vec![Test::One, Test::Two, Test::Three, Test::Four]);
300 }
301
302 #[test]
303 fn range_reverse_inclusive_none_none() {
304 let v: Vec<Test> = range_inclusive(None, None).rev().collect();
305
306 assert_eq!(v, vec![Test::Four, Test::Three, Test::Two, Test::One]);
307 }
308
309 #[test]
310 fn range_inclusive_upper() {
311 let v: Vec<Test> = range_inclusive(None, Some(Test::Three)).collect();
312
313 assert_eq!(v, vec![Test::One, Test::Two, Test::Three]);
314 }
315
316 #[test]
317 fn range_reverse_inclusive_upper() {
318 let v: Vec<Test> = range_inclusive(None, Some(Test::Three)).rev().collect();
319
320 assert_eq!(v, vec![Test::Three, Test::Two, Test::One]);
321 }
322
323 #[test]
324 fn range_inclusive_lower() {
325 let v: Vec<Test> = range_inclusive(Some(Test::Two), None).collect();
326
327 assert_eq!(v, vec![Test::Two, Test::Three, Test::Four]);
328 }
329
330 #[test]
331 fn range_reverse_inclusive_lower() {
332 let v: Vec<Test> = range_inclusive(Some(Test::Two), None).rev().collect();
333
334 assert_eq!(v, vec![Test::Four, Test::Three, Test::Two]);
335 }
336
337 #[test]
338 fn range_inclusive_upper_lower() {
339 let v: Vec<Test> = range_inclusive(Some(Test::Two), Some(Test::Three)).collect();
340
341 assert_eq!(v, vec![Test::Two, Test::Three]);
342 }
343
344 #[test]
345 fn range_reverse_inclusive_upper_lower() {
346 let v: Vec<Test> = range_inclusive(Some(Test::Two), Some(Test::Three))
347 .rev()
348 .collect();
349
350 assert_eq!(v, vec![Test::Three, Test::Two]);
351 }
352}