1use super::*;
2
3pub trait RangeStepExtension
4{
5 type Output: Iterator<Item = Self::Item> + DoubleEndedIterator + FusedIterator;
6 type Item;
7 fn step(self, step: Self::Item) -> Self::Output;
9 fn step_by_one(self) -> Self::Output
10 where
11 Self: Sized,
12 Self::Item: One,
13 {
14 self.step(Self::Item::ONE)
15 }
16}
17
18pub trait RangeStepIter: Primitive
20{
21 fn iter(max_excluded: Self) -> RangeStep<Self>
23 {
24 RangeStep {
25 idx: Self::ZERO,
26 end: max_excluded,
27 step: Self::ONE,
28 }
29 }
30}
31impl<T> RangeStepIter for T where T: Primitive {}
32
33pub trait RangeDefaultStepExtension: RangeDefault
34where
35 Range<Self>: RangeStepExtension,
36{
37 fn step(
39 self,
40 step: <Range<Self> as RangeStepExtension>::Item,
41 ) -> <Range<Self> as RangeStepExtension>::Output;
42}
43impl<T> RangeDefaultStepExtension for T
44where
45 T: RangeDefault,
46 Range<T>: RangeStepExtension,
47{
48 fn step(
49 self,
50 step: <Range<Self> as RangeStepExtension>::Item,
51 ) -> <Range<Self> as RangeStepExtension>::Output
52 {
53 (Self::RANGE_MIN..Self::RANGE_MAX).step(step)
54 }
55}
56pub trait RangeDefaultStepInclusiveExtension: RangeDefault
57where
58 RangeInclusive<Self>: RangeStepExtension,
59{
60 fn step_inclusive(
62 self,
63 step: <RangeInclusive<Self> as RangeStepExtension>::Item,
64 ) -> <RangeInclusive<Self> as RangeStepExtension>::Output;
65}
66impl<T> RangeDefaultStepInclusiveExtension for T
67where
68 T: RangeDefault,
69 RangeInclusive<T>: RangeStepExtension,
70{
71 fn step_inclusive(
72 self,
73 step: <RangeInclusive<Self> as RangeStepExtension>::Item,
74 ) -> <RangeInclusive<Self> as RangeStepExtension>::Output
75 {
76 (Self::RANGE_MIN..=Self::RANGE_MAX).step(step)
77 }
78}
79
80#[derive(Clone, PartialEq, Debug, Hash)]
83#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
84pub struct RangeStep<T>
85where
86 T: Primitive,
87{
88 pub idx: T,
89 pub end: T,
90 pub step: T,
91}
92
93impl<T> Iterator for RangeStep<T>
94where
95 T: Primitive,
96{
97 type Item = T;
98 fn next(&mut self) -> Option<Self::Item>
99 {
100 if self.idx <= self.end
101 {
102 let val = self.idx;
103 self.idx += self.step;
104
105 match T::PRIMITIVE_TYPE
106 {
107 NumberType::IntegerUnsigned | NumberType::IntegerSigned => Some(val),
108 NumberType::Float =>
109 {
110 if self.idx == val
111 {
112 None
113 }
114 else
115 {
116 Some(val)
117 }
118 }
119 NumberType::Bool =>
120 unsafe { unreachable_unchecked() },
121 }
122 }
123 else
124 {
125 None
126 }
127 }
128}
129impl<T> DoubleEndedIterator for RangeStep<T>
130where
131 T: Primitive,
132{
133 fn next_back(&mut self) -> Option<Self::Item>
134 {
135 if self.end >= self.idx
136 {
137 let val = self.end;
138 self.end -= self.step;
139
140 match T::PRIMITIVE_TYPE
141 {
142 NumberType::IntegerUnsigned | NumberType::IntegerSigned => Some(val),
143 NumberType::Float =>
145 {
146 if self.end == val
147 {
148 None
149 }
150 else
151 {
152 Some(val)
153 }
154 }
155 NumberType::Bool =>
156 unsafe { unreachable_unchecked() },
157 }
158 }
159 else
160 {
161 match T::PRIMITIVE_TYPE
162 {
163 NumberType::IntegerUnsigned | NumberType::IntegerSigned => None,
164 NumberType::Float =>
166 {
167 if self.end + self.step > self.idx
169 {
170 self.step = T::ZERO;
171 self.end = self.idx;
172 Some(self.idx)
173 }
174 else
175 {
176 None
177 }
178 }
179 NumberType::Bool =>
180 unsafe { unreachable_unchecked() },
181 }
182 }
183 }
184}
185impl<T> FusedIterator for RangeStep<T> where T: Primitive {}
186
187impl<T> RangeStepExtension for Range<T>
188where
189 T: Primitive,
190{
191 type Output = RangeStep<T>;
192 type Item = T;
193 fn step(self, step: T) -> Self::Output
194 {
195 RangeStep {
196 idx: self.start,
197 end: self.end - step,
198 step,
199 }
200 }
201}
202impl<T> RangeStepExtension for RangeTo<T>
203where
204 T: Primitive + RangeDefault,
205{
206 type Output = RangeStep<T>;
207 type Item = T;
208 fn step(self, step: T) -> Self::Output { (T::RANGE_MIN..self.end).step(step) }
209}
210
211#[derive(Clone, PartialEq, Debug, Hash)]
214#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
215pub struct RangeStepInclusive<T>
216where
217 T: Primitive,
218{
219 pub idx: T,
220 pub end: T,
221 pub step: T,
222}
223
224impl<T> Iterator for RangeStepInclusive<T>
225where
226 T: Primitive,
227{
228 type Item = T;
229 fn next(&mut self) -> Option<Self::Item>
230 {
231 if self.idx <= self.end
232 {
233 let val = self.idx;
234 self.idx += self.step;
235
236 match T::PRIMITIVE_TYPE
237 {
238 NumberType::IntegerUnsigned | NumberType::IntegerSigned => Some(val),
239 NumberType::Float =>
241 {
242 if self.idx == val
243 {
244 None
245 }
246 else
247 {
248 Some(val)
249 }
250 }
251 NumberType::Bool =>
252 unsafe { unreachable_unchecked() },
253 }
254 }
255 else
256 {
257 match T::PRIMITIVE_TYPE
258 {
259 NumberType::IntegerUnsigned | NumberType::IntegerSigned => None,
260 NumberType::Float =>
262 {
263 if self.idx - self.step < self.end
265 {
266 self.step = T::ZERO;
267 self.idx = self.end;
268 Some(self.end)
269 }
270 else
271 {
272 None
273 }
274 }
275 NumberType::Bool =>
276 unsafe { unreachable_unchecked() },
277 }
278 }
279 }
280}
281impl<T> DoubleEndedIterator for RangeStepInclusive<T>
282where
283 T: Primitive,
284{
285 fn next_back(&mut self) -> Option<Self::Item>
286 {
287 if self.end >= self.idx
288 {
289 let val = self.end;
290 self.end -= self.step;
291
292 match T::PRIMITIVE_TYPE
293 {
294 NumberType::IntegerUnsigned | NumberType::IntegerSigned => Some(val),
295 NumberType::Float =>
297 {
298 if self.end == val
299 {
300 return None;
301 }
302 else
303 {
304 Some(val)
305 }
306 }
307 NumberType::Bool =>
308 unsafe { unreachable_unchecked() },
309 }
310 }
311 else
312 {
313 match T::PRIMITIVE_TYPE
314 {
315 NumberType::IntegerUnsigned | NumberType::IntegerSigned => None,
316 NumberType::Float =>
318 {
319 if self.end + self.step > self.idx
321 {
322 self.step = T::ZERO;
323 self.end = self.idx;
324 Some(self.idx)
325 }
326 else
327 {
328 None
329 }
330 }
331 NumberType::Bool =>
332 unsafe { unreachable_unchecked() },
333 }
334 }
335 }
336}
337impl<T> FusedIterator for RangeStepInclusive<T> where T: Primitive {}
338
339impl<T> RangeStepExtension for RangeFrom<T>
340where
341 T: Primitive + RangeDefault,
342{
343 type Output = RangeStepInclusive<T>;
344 type Item = T;
345 fn step(self, step: T) -> Self::Output { (self.start..=T::RANGE_MAX).step(step) }
346}
347impl<T> RangeStepExtension for RangeInclusive<T>
348where
349 T: Primitive,
350{
351 type Output = RangeStepInclusive<T>;
352 type Item = T;
353 fn step(self, step: T) -> Self::Output
354 {
355 let (start, end) = self.into_inner();
356 RangeStepInclusive {
357 idx: start,
358 end,
359 step,
360 }
361 }
362}
363impl<T> RangeStepExtension for RangeToInclusive<T>
364where
365 T: Primitive + RangeDefault,
366{
367 type Output = RangeStepInclusive<T>;
368 type Item = T;
369 fn step(self, step: T) -> Self::Output { (T::RANGE_MIN..=self.end).step(step) }
370}
371
372#[cfg(test)]
373mod range_test
374{
375 use super::*;
376
377 #[test]
378 fn range()
379 {
380 assert_eq!((-2..5).step(1).to_vec(), vec![-2, -1, 0, 1, 2, 3, 4]);
381 }
382
383 #[test]
384 fn range_rev()
385 {
386 assert_eq!((-2..5).step(1).rev().to_vec(), vec![4, 3, 2, 1, 0, -1, -2]);
387 }
388
389 #[test]
390 fn range_inclusive()
391 {
392 assert_eq!((-2..=5).step(1).to_vec(), vec![-2, -1, 0, 1, 2, 3, 4, 5]);
393 }
394
395 #[test]
396 fn range_inclusive_rev()
397 {
398 assert_eq!(
399 (-2..=5).step(1).rev().to_vec(),
400 vec![5, 4, 3, 2, 1, 0, -1, -2]
401 );
402 }
403
404 #[test]
405 fn range_float()
406 {
407 assert_eq!((0.5..2.5).step(1.).to_vec(), vec![0.5, 1.5]);
408 }
409
410 #[test]
411 fn range_rev_float()
412 {
413 assert_eq!((0.5..2.5).step(1.).rev().to_vec(), vec![1.5, 0.5]);
414 }
415
416 #[test]
417 fn range_inclusive_float()
418 {
419 assert_eq!((0.5..=2.5).step(1.).to_vec(), vec![0.5, 1.5, 2.5]);
420 }
421
422 #[test]
423 fn range_inclusive_rev_float()
424 {
425 assert_eq!((0.5..=2.5).step(1.).rev().to_vec(), vec![2.5, 1.5, 0.5]);
426 }
427
428 #[test]
429 fn range_float_2()
430 {
431 let values = (0.0..1.0).step(0.3).to_vec();
432 assert_eq!(values.len(), 3);
433 assert_eq!(values[0], 0.0);
434 assert!(values.last().copied().unwrap() <= 0.95);
435 }
436
437 #[test]
438 fn range_rev_float_2()
439 {
440 let values = (0.0..1.0f32).step(0.3).rev().to_vec();
441 assert_eq!(values.len(), 4);
442 assert!((values[0] - 0.7).abs() <= 0.00001);
443 assert_eq!(values.last().copied().unwrap(), 0.);
444 }
445
446 #[test]
447 fn range_inclusive_float_2()
448 {
449 let values = (0.0..=1.0).step(0.3).to_vec();
450 assert_eq!(values.len(), 5);
451 assert_eq!(values[0], 0.0);
452 assert_eq!(values.last().copied().unwrap(), 1.0);
453 }
454
455 #[test]
456 fn range_inclusive_rev_float_2()
457 {
458 let values = (0.0..=1.0).step(0.3).rev().to_vec();
459 assert_eq!(values.len(), 5);
460 assert_eq!(values[0], 1.0);
461 assert_eq!(values.last().copied().unwrap(), 0.);
462 }
463}