diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2013-07-18 19:50:51 -0400 |
|---|---|---|
| committer | Daniel Micay <danielmicay@gmail.com> | 2013-07-19 20:37:37 -0400 |
| commit | 404de4f4aed8902e882fda35565a3e6100f6743f (patch) | |
| tree | de24bc27805bc3fd20bb5887b48537149f4b3b2e /src | |
| parent | 0d04aa78e5e8a7e3c48141028137c1a69e7e32ee (diff) | |
| download | rust-404de4f4aed8902e882fda35565a3e6100f6743f.tar.gz rust-404de4f4aed8902e882fda35565a3e6100f6743f.zip | |
iterator: impl DoubleEndedIterator for adaptors
Diffstat (limited to 'src')
| -rw-r--r-- | src/libstd/iterator.rs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index b9593d845a4..c8cde69197b 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -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> { @@ -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, @@ -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, @@ -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> { @@ -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>, @@ -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) + } } |
