use Traversal;
use std::num::{Int, ToPrimitive};
use std::ops::Add;
#[derive(Copy, Clone)]
pub struct Counter<A> {
start: A,
step: A,
}
#[inline]
pub fn count<A>(start: A, step: A) -> Counter<A> {
Counter{ start: start, step: step }
}
impl<A: Add<Output=A> + Clone> Traversal for Counter<A> {
type Item = A;
#[inline]
fn foreach<F>(self, mut f: F) where F: FnMut(A) -> bool {
let mut i = self.start;
loop {
let old = i;
i = old.clone() + self.step.clone();
if f(old) { return; }
}
}
}
#[derive(Copy, Clone)]
pub struct Range<A> {
start: A,
stop: A,
}
#[inline]
pub fn range<A: Int>(start: A, stop: A) -> Range<A> {
Range { start: start, stop: stop }
}
impl<A: Int + ToPrimitive> Traversal for Range<A> {
type Item = A;
#[inline]
fn foreach<F>(self, mut f: F) where F: FnMut(A) -> bool {
let mut i = self.start;
let one = Int::one();
while i < self.stop {
let old = i;
i = old + one;
if f(old) { return; }
}
}
}
#[derive(Copy, Clone)]
pub struct RangeInclusive<A> {
start: A,
stop: A,
}
#[inline]
pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
RangeInclusive { start: start, stop: stop }
}
impl<A: Int + ToPrimitive> Traversal for RangeInclusive<A> {
type Item = A;
#[inline]
fn foreach<F>(self, mut f: F) where F: FnMut(A) -> bool {
let mut i = self.start;
let one = Int::one();
while i <= self.stop {
let old = i;
i = old + one;
if f(old) { return; }
}
}
}
#[derive(Copy, Clone)]
pub struct RangeStep<A> {
start: A,
stop: A,
step: A,
}
#[inline]
pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
RangeStep { start: start, stop: stop, step: step }
}
impl<A: Int> Traversal for RangeStep<A> {
type Item = A;
#[inline]
fn foreach<F>(self, mut f: F) where F: FnMut(A) -> bool {
let mut i = self.start;
if self.step > Int::zero() {
while i < self.stop {
let old = i;
let temp = i.checked_add(self.step);
if f(old) { return; }
i = match temp { None => return, Some(x) => x }
}
} else {
while i > self.stop {
let old = i;
let temp = i.checked_add(self.step);
if f(old) { return; }
i = match temp { None => return, Some(x) => x }
}
}
}
}
#[derive(Copy, Clone)]
pub struct RangeStepInclusive<A> {
start: A,
stop: A,
step: A,
}
#[inline]
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
RangeStepInclusive { start: start, stop: stop, step: step }
}
impl<A: Int> Traversal for RangeStepInclusive<A> {
type Item = A;
#[inline]
fn foreach<F>(self, mut f: F) where F: FnMut(A) -> bool {
let mut i = self.start;
if self.step > Int::zero() {
while i <= self.stop {
let old = i;
let temp = i.checked_add(self.step);
if f(old) { return; }
i = match temp { None => return, Some(x) => x }
}
} else {
while i >= self.stop {
let old = i;
let temp = i.checked_add(self.step);
if f(old) { return; }
i = match temp { None => return, Some(x) => x }
}
}
}
}
#[inline]
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
Repeat{ element: elt }
}
#[derive(Copy, Clone)]
pub struct Repeat<A> {
element: A
}
impl<A: Clone> Traversal for Repeat<A> {
type Item = A;
#[inline]
fn foreach<F>(self, mut f: F) where F: FnMut(A) -> bool {
loop {
if f(self.element.clone()) { return; }
}
}
}
#[derive(Copy, Clone)]
pub struct Iterate<T, F> {
seed: T,
iter: F,
}
#[inline]
pub fn iterate<T, F>(seed: T, f: F) -> Iterate<T, F> where
T: Clone,
F: FnMut(T) -> T
{
Iterate { seed: seed, iter: f }
}
impl<A, I> Traversal for Iterate<A, I> where
A: Clone,
I: FnMut(A) -> A {
type Item = A;
#[inline]
fn foreach<F>(mut self, mut f: F) where F: FnMut(A) -> bool {
if !f(self.seed.clone()) {
let mut cur = self.seed;
loop {
let next = (self.iter)(cur);
if f(next.clone()) { return; }
cur = next;
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use Traversal;
#[test]
fn test_range() {
assert_eq!(range(0, 5).collect::<Vec<i32>>(), vec![0, 1, 2, 3, 4]);
assert_eq!(range(-10, -1).collect::<Vec<i32>>(),
vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
assert_eq!(range(200i32, -5).count(), 0);
assert_eq!(range(200i32, 200).count(), 0);
}
#[test]
fn test_range_inclusive() {
assert_eq!(range_inclusive(0, 5).collect::<Vec<i32>>(), vec![0, 1, 2, 3, 4, 5]);
assert_eq!(range_inclusive(200i32, -5).count(), 0);
assert_eq!(range_inclusive(200, 200).collect::<Vec<i32>>(), vec![200]);
}
#[test]
fn test_range_step() {
assert_eq!(range_step(0, 20, 5).collect::<Vec<i32>>(), vec![0, 5, 10, 15]);
assert_eq!(range_step(20, 0, -5).collect::<Vec<i32>>(), vec![20, 15, 10, 5]);
assert_eq!(range_step(20, 0, -6).collect::<Vec<i32>>(), vec![20, 14, 8, 2]);
assert_eq!(range_step(200u8, 255, 50).collect::<Vec<u8>>(), vec![200u8, 250]);
assert_eq!(range_step(200, -5, 1).collect::<Vec<i32>>(), vec![]);
assert_eq!(range_step(200, 200, 1).collect::<Vec<i32>>(), vec![]);
}
#[test]
fn test_range_step_inclusive() {
assert_eq!(range_step_inclusive(0, 20, 5).collect::<Vec<i32>>(), vec![0, 5, 10, 15, 20]);
assert_eq!(range_step_inclusive(20, 0, -5).collect::<Vec<i32>>(), vec![20, 15, 10, 5, 0]);
assert_eq!(range_step_inclusive(20, 0, -6).collect::<Vec<i32>>(), vec![20, 14, 8, 2]);
assert_eq!(range_step_inclusive(200, 255, 50).collect::<Vec<u8>>(), vec![200, 250]);
assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<i32>>(), vec![]);
assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<i32>>(), vec![200]);
}
#[test]
fn test_iterate() {
assert_eq!(iterate(1, |x| x * 2).take(5).collect::<Vec<i32>>(), vec![1, 2, 4, 8, 16]);
}
#[test]
fn test_repeat() {
assert_eq!(repeat(42).take(5).collect::<Vec<i32>>(), vec![42, 42, 42, 42, 42]);
}
}