From 404de4f4aed8902e882fda35565a3e6100f6743f Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Thu, 18 Jul 2013 19:50:51 -0400 Subject: [PATCH] iterator: impl DoubleEndedIterator for adaptors --- src/libstd/iterator.rs | 121 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index b9593d845a4cb..c8cde69197b23 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -773,6 +773,17 @@ impl, U: Iterator> Iterator for ChainIterator { } } +impl, U: DoubleEndedIterator> DoubleEndedIterator +for ChainIterator { + #[inline] + fn next_back(&mut self) -> Option { + 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 { @@ -828,6 +839,17 @@ impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { } } +impl<'self, A, B, T: DoubleEndedIterator> DoubleEndedIterator +for MapIterator<'self, A, B, T> { + #[inline] + fn next_back(&mut self) -> Option { + 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> Iterator for FilterIterator<'self, A, T> { } } +impl<'self, A, T: DoubleEndedIterator> DoubleEndedIterator for FilterIterator<'self, A, T> { + #[inline] + fn next_back(&mut self) -> Option { + 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> Iterator for FilterMapIterator<'self, A, B, } } +impl<'self, A, B, T: DoubleEndedIterator> DoubleEndedIterator +for FilterMapIterator<'self, A, B, T> { + #[inline] + fn next_back(&mut self) -> Option { + 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 { @@ -1135,6 +1193,20 @@ impl<'self, A, T: Iterator> Iterator for PeekIterator<'self, A, T> { } } +impl<'self, A, T: DoubleEndedIterator> DoubleEndedIterator for PeekIterator<'self, A, T> { + #[inline] + fn next_back(&mut self) -> Option { + 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, @@ -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) + } }