diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2013-09-14 16:47:21 -0400 |
|---|---|---|
| committer | Daniel Micay <danielmicay@gmail.com> | 2013-09-14 18:26:21 -0400 |
| commit | a18038f3b2ee338de05ef4489d6ac7067c9198fd (patch) | |
| tree | ab70666937bd3d1ece95a305f8bd824027473af2 | |
| parent | 3aead52586d26f375e6318fb6980280db18b70b7 (diff) | |
| download | rust-a18038f3b2ee338de05ef4489d6ac7067c9198fd.tar.gz rust-a18038f3b2ee338de05ef4489d6ac7067c9198fd.zip | |
iter: add `RangeStep` and `RangeStepInclusive`
| -rw-r--r-- | src/libstd/iter.rs | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index faa2d715df4..22e8a1defbd 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -21,7 +21,7 @@ use cmp; use num::{Zero, One, Integer, CheckedAdd, CheckedSub, Saturating}; use option::{Option, Some, None}; use ops::{Add, Mul, Sub}; -use cmp::Ord; +use cmp::{Eq, Ord}; use clone::Clone; use uint; use util; @@ -1838,6 +1838,81 @@ impl<A: Sub<A, A> + Integer + Ord + Clone> DoubleEndedIterator<A> for RangeInclu } } +/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. +#[deriving(Clone, DeepClone)] +pub struct RangeStep<A> { + priv state: A, + priv stop: A, + priv step: A, + priv rev: bool +} + +/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. +#[inline] +pub fn range_step<A: CheckedAdd + Ord + Clone + Zero>(start: A, stop: A, step: A) -> RangeStep<A> { + let rev = step < Zero::zero(); + RangeStep{state: start, stop: stop, step: step, rev: rev} +} + +impl<A: CheckedAdd + Ord + Clone> Iterator<A> for RangeStep<A> { + #[inline] + fn next(&mut self) -> Option<A> { + if (self.rev && self.state > self.stop) || self.state < self.stop { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.state = self.stop.clone() + } + Some(result) + } else { + None + } + } +} + +/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. +#[deriving(Clone, DeepClone)] +pub struct RangeStepInclusive<A> { + priv state: A, + priv stop: A, + priv step: A, + priv rev: bool, + priv done: bool +} + +/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. +#[inline] +pub fn range_step_inclusive<A: CheckedAdd + Ord + Clone + Zero>(start: A, stop: A, + step: A) -> RangeStepInclusive<A> { + let rev = step < Zero::zero(); + RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} +} + +impl<A: CheckedAdd + Ord + Clone + Eq> Iterator<A> for RangeStepInclusive<A> { + #[inline] + fn next(&mut self) -> Option<A> { + if !self.done { + if (self.rev && self.state > self.stop) || self.state < self.stop { + let result = self.state.clone(); + match self.state.checked_add(&self.step) { + Some(x) => self.state = x, + None => self.done = true + } + Some(result) + } else { + if self.state == self.stop { + self.done = true; + Some(self.state.clone()) + } else { + None + } + } + } else { + None + } + } +} + /// An iterator that repeats an element endlessly #[deriving(Clone, DeepClone)] pub struct Repeat<A> { @@ -2648,6 +2723,20 @@ mod tests { } #[test] + fn test_range_step() { + assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15]); + assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5]); + assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]); + } + + #[test] + fn test_range_step_inclusive() { + assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15, 20]); + assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5, 0]); + assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]); + } + + #[test] fn test_reverse() { let mut ys = [1, 2, 3, 4, 5]; ys.mut_iter().reverse_(); |
