#![warn(missing_docs)]
extern crate num_traits;
use num_traits::One;
use std::iter::FromIterator;
use std::ops::{AddAssign, SubAssign};
pub fn from<Idx>(i: Idx) -> From<Idx> {
From { from: i }
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
pub struct From<Idx> {
from: Idx,
}
impl<Idx> From<Idx> {
pub fn up_to(self, x: Idx) -> Range<Idx, Upwards> {
Range {
from: self.from,
to: x,
direction: Upwards,
}
}
pub fn down_to(self, x: Idx) -> Range<Idx, Downwards> {
Range {
from: self.from,
to: x,
direction: Downwards,
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
pub struct Range<Idx, Direction> {
direction: Direction,
from: Idx,
to: Idx,
}
#[doc(hidden)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
pub struct Upwards;
#[doc(hidden)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
pub struct Downwards;
impl<Idx> Range<Idx, Upwards>
where
Idx: Clone + PartialEq + One + AddAssign + SubAssign,
{
pub fn collect<B>(self) -> B
where
B: FromIterator<Idx>,
{
self.into_iter().collect()
}
pub fn to_vec(&self) -> Vec<Idx> {
self.clone().into_iter().collect()
}
}
impl<Idx> Range<Idx, Downwards>
where
Idx: Clone + PartialEq + One + AddAssign + SubAssign,
{
pub fn collect<B>(self) -> B
where
B: FromIterator<Idx>,
{
self.into_iter().collect()
}
pub fn to_vec(&self) -> Vec<Idx> {
self.clone().into_iter().collect()
}
}
impl<Idx> IntoIterator for Range<Idx, Upwards>
where
Idx: Clone + PartialEq + One + AddAssign + SubAssign,
{
type Item = Idx;
type IntoIter = RangeIter<Idx, Upwards>;
fn into_iter(self) -> Self::IntoIter {
RangeIter {
current: self.from,
limit: self.to,
direction: self.direction,
init: false,
}
}
}
impl<Idx> IntoIterator for Range<Idx, Downwards>
where
Idx: Clone + PartialEq + One + AddAssign + SubAssign,
{
type Item = Idx;
type IntoIter = RangeIter<Idx, Downwards>;
fn into_iter(self) -> Self::IntoIter {
RangeIter {
current: self.from,
limit: self.to,
direction: self.direction,
init: false,
}
}
}
pub struct RangeIter<Idx, Direction> {
current: Idx,
limit: Idx,
#[allow(unused)]
direction: Direction,
init: bool,
}
impl<Idx> Iterator for RangeIter<Idx, Upwards>
where
Idx: Clone + PartialEq + One + AddAssign + SubAssign,
{
type Item = Idx;
fn next(&mut self) -> Option<Self::Item> {
if !self.init {
self.init = true;
return Some(self.current.clone());
}
if self.current == self.limit {
return None;
}
self.current += Idx::one();
Some(self.current.clone())
}
}
impl<Idx> Iterator for RangeIter<Idx, Downwards>
where
Idx: Clone + PartialEq + One + AddAssign + SubAssign,
{
type Item = Idx;
fn next(&mut self) -> Option<Self::Item> {
if !self.init {
self.init = true;
return Some(self.current.clone());
}
if self.current == self.limit {
return None;
}
self.current -= Idx::one();
Some(self.current.clone())
}
}
#[test]
fn range_collect() {
let x: Vec<i32> = from(10).up_to(14).into_iter().take(10).collect();
assert_eq!(x, vec![10, 11, 12, 13, 14]);
}
#[test]
fn rev_range_collect() {
let x: Vec<i32> = from(14).down_to(10).into_iter().take(10).collect();
assert_eq!(x, vec![14, 13, 12, 11, 10]);
}