Skip to content

Commit

Permalink
iterator: impl DoubleEndedIterator for adaptors
Browse files Browse the repository at this point in the history
  • Loading branch information
thestinger committed Jul 20, 2013
1 parent 0d04aa7 commit 404de4f
Showing 1 changed file with 121 additions and 0 deletions.
121 changes: 121 additions & 0 deletions src/libstd/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,17 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
}
}

impl<A, T: DoubleEndedIterator<A>, U: DoubleEndedIterator<A>> DoubleEndedIterator<A>
for ChainIterator<A, T, U> {
#[inline]
fn next_back(&mut self) -> Option<A> {
match self.b.next_back() {
Some(x) => Some(x),
None => self.a.next_back()
}
}
}

/// An iterator which iterates two other iterators simultaneously
// FIXME #6967: Dummy A & B parameters to get around type inference bug
pub struct ZipIterator<A, T, B, U> {
Expand Down Expand Up @@ -828,6 +839,17 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
}
}

impl<'self, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B>
for MapIterator<'self, A, B, T> {
#[inline]
fn next_back(&mut self) -> Option<B> {
match self.iter.next_back() {
Some(a) => Some((self.f)(a)),
_ => None
}
}
}

/// An iterator which filters the elements of `iter` with `predicate`
pub struct FilterIterator<'self, A, T> {
priv iter: T,
Expand All @@ -854,6 +876,24 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
}
}

impl<'self, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for FilterIterator<'self, A, T> {
#[inline]
fn next_back(&mut self) -> Option<A> {
loop {
match self.iter.next_back() {
None => return None,
Some(x) => {
if (self.predicate)(&x) {
return Some(x);
} else {
loop
}
}
}
}
}
}

/// An iterator which uses `f` to both filter and map elements from `iter`
pub struct FilterMapIterator<'self, A, B, T> {
priv iter: T,
Expand All @@ -879,6 +919,24 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B,
}
}

impl<'self, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B>
for FilterMapIterator<'self, A, B, T> {
#[inline]
fn next_back(&mut self) -> Option<B> {
loop {
match self.iter.next_back() {
None => return None,
Some(x) => {
match (self.f)(x) {
Some(y) => return Some(y),
None => ()
}
}
}
}
}
}

/// An iterator which yields the current count and the element during iteration
// FIXME #6967: Dummy A parameter to get around type inference bug
pub struct EnumerateIterator<A, T> {
Expand Down Expand Up @@ -1135,6 +1193,20 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for PeekIterator<'self, A, T> {
}
}

impl<'self, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for PeekIterator<'self, A, T> {
#[inline]
fn next_back(&mut self) -> Option<A> {
let next = self.iter.next_back();

match next {
Some(ref a) => (self.f)(a),
None => ()
}

next
}
}

/// An iterator which just modifies the contained state throughout iteration.
pub struct UnfoldrIterator<'self, A, St> {
priv f: &'self fn(&mut St) -> Option<A>,
Expand Down Expand Up @@ -1526,4 +1598,53 @@ mod tests {
it.next();
assert_eq!(it.invert().transform(|&x| x).collect::<~[int]>(), ~[16, 14, 12, 10, 8, 6]);
}

#[test]
fn test_double_ended_map() {
let xs = [1, 2, 3, 4, 5, 6];
let mut it = xs.iter().transform(|&x| x * -1);
assert_eq!(it.next(), Some(-1));
assert_eq!(it.next(), Some(-2));
assert_eq!(it.next_back(), Some(-6));
assert_eq!(it.next_back(), Some(-5));
assert_eq!(it.next(), Some(-3));
assert_eq!(it.next_back(), Some(-4));
assert_eq!(it.next(), None);
}

#[test]
fn test_double_ended_filter() {
let xs = [1, 2, 3, 4, 5, 6];
let mut it = xs.iter().filter(|&x| *x & 1 == 0);
assert_eq!(it.next_back().unwrap(), &6);
assert_eq!(it.next_back().unwrap(), &4);
assert_eq!(it.next().unwrap(), &2);
assert_eq!(it.next_back(), None);
}

#[test]
fn test_double_ended_filter_map() {
let xs = [1, 2, 3, 4, 5, 6];
let mut it = xs.iter().filter_map(|&x| if x & 1 == 0 { Some(x * 2) } else { None });
assert_eq!(it.next_back().unwrap(), 12);
assert_eq!(it.next_back().unwrap(), 8);
assert_eq!(it.next().unwrap(), 4);
assert_eq!(it.next_back(), None);
}

#[test]
fn test_double_ended_chain() {
let xs = [1, 2, 3, 4, 5];
let ys = ~[7, 9, 11];
let mut it = xs.iter().chain_(ys.iter()).invert();
assert_eq!(it.next().unwrap(), &11)
assert_eq!(it.next().unwrap(), &9)
assert_eq!(it.next_back().unwrap(), &1)
assert_eq!(it.next_back().unwrap(), &2)
assert_eq!(it.next_back().unwrap(), &3)
assert_eq!(it.next_back().unwrap(), &4)
assert_eq!(it.next_back().unwrap(), &5)
assert_eq!(it.next_back().unwrap(), &7)
assert_eq!(it.next_back(), None)
}
}

0 comments on commit 404de4f

Please sign in to comment.