Skip to content

Commit a18038f

Browse files
committed
iter: add RangeStep and RangeStepInclusive
1 parent 3aead52 commit a18038f

File tree

1 file changed

+90
-1
lines changed

1 file changed

+90
-1
lines changed

src/libstd/iter.rs

+90-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use cmp;
2121
use num::{Zero, One, Integer, CheckedAdd, CheckedSub, Saturating};
2222
use option::{Option, Some, None};
2323
use ops::{Add, Mul, Sub};
24-
use cmp::Ord;
24+
use cmp::{Eq, Ord};
2525
use clone::Clone;
2626
use uint;
2727
use util;
@@ -1838,6 +1838,81 @@ impl<A: Sub<A, A> + Integer + Ord + Clone> DoubleEndedIterator<A> for RangeInclu
18381838
}
18391839
}
18401840

1841+
/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
1842+
#[deriving(Clone, DeepClone)]
1843+
pub struct RangeStep<A> {
1844+
priv state: A,
1845+
priv stop: A,
1846+
priv step: A,
1847+
priv rev: bool
1848+
}
1849+
1850+
/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
1851+
#[inline]
1852+
pub fn range_step<A: CheckedAdd + Ord + Clone + Zero>(start: A, stop: A, step: A) -> RangeStep<A> {
1853+
let rev = step < Zero::zero();
1854+
RangeStep{state: start, stop: stop, step: step, rev: rev}
1855+
}
1856+
1857+
impl<A: CheckedAdd + Ord + Clone> Iterator<A> for RangeStep<A> {
1858+
#[inline]
1859+
fn next(&mut self) -> Option<A> {
1860+
if (self.rev && self.state > self.stop) || self.state < self.stop {
1861+
let result = self.state.clone();
1862+
match self.state.checked_add(&self.step) {
1863+
Some(x) => self.state = x,
1864+
None => self.state = self.stop.clone()
1865+
}
1866+
Some(result)
1867+
} else {
1868+
None
1869+
}
1870+
}
1871+
}
1872+
1873+
/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
1874+
#[deriving(Clone, DeepClone)]
1875+
pub struct RangeStepInclusive<A> {
1876+
priv state: A,
1877+
priv stop: A,
1878+
priv step: A,
1879+
priv rev: bool,
1880+
priv done: bool
1881+
}
1882+
1883+
/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
1884+
#[inline]
1885+
pub fn range_step_inclusive<A: CheckedAdd + Ord + Clone + Zero>(start: A, stop: A,
1886+
step: A) -> RangeStepInclusive<A> {
1887+
let rev = step < Zero::zero();
1888+
RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false}
1889+
}
1890+
1891+
impl<A: CheckedAdd + Ord + Clone + Eq> Iterator<A> for RangeStepInclusive<A> {
1892+
#[inline]
1893+
fn next(&mut self) -> Option<A> {
1894+
if !self.done {
1895+
if (self.rev && self.state > self.stop) || self.state < self.stop {
1896+
let result = self.state.clone();
1897+
match self.state.checked_add(&self.step) {
1898+
Some(x) => self.state = x,
1899+
None => self.done = true
1900+
}
1901+
Some(result)
1902+
} else {
1903+
if self.state == self.stop {
1904+
self.done = true;
1905+
Some(self.state.clone())
1906+
} else {
1907+
None
1908+
}
1909+
}
1910+
} else {
1911+
None
1912+
}
1913+
}
1914+
}
1915+
18411916
/// An iterator that repeats an element endlessly
18421917
#[deriving(Clone, DeepClone)]
18431918
pub struct Repeat<A> {
@@ -2647,6 +2722,20 @@ mod tests {
26472722
assert_eq!(range_inclusive(0i, 5).invert().collect::<~[int]>(), ~[5i, 4, 3, 2, 1, 0]);
26482723
}
26492724

2725+
#[test]
2726+
fn test_range_step() {
2727+
assert_eq!(range_step(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15]);
2728+
assert_eq!(range_step(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5]);
2729+
assert_eq!(range_step(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]);
2730+
}
2731+
2732+
#[test]
2733+
fn test_range_step_inclusive() {
2734+
assert_eq!(range_step_inclusive(0i, 20, 5).collect::<~[int]>(), ~[0, 5, 10, 15, 20]);
2735+
assert_eq!(range_step_inclusive(20i, 0, -5).collect::<~[int]>(), ~[20, 15, 10, 5, 0]);
2736+
assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<~[u8]>(), ~[200u8, 250]);
2737+
}
2738+
26502739
#[test]
26512740
fn test_reverse() {
26522741
let mut ys = [1, 2, 3, 4, 5];

0 commit comments

Comments
 (0)