diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs index 11d7bc6c1bf89..06858a05a49bf 100644 --- a/src/libstd/iter.rs +++ b/src/libstd/iter.rs @@ -285,7 +285,7 @@ pub trait Iterator { /// ``` #[inline] fn skip(self, n: uint) -> Skip { - Skip{iter: self, n: n} + Skip{iter: self, n: n, consumed_back: 0} } /// Creates an iterator which yields the first `n` elements of this @@ -303,7 +303,7 @@ pub trait Iterator { /// ``` #[inline] fn take(self, n: uint) -> Take { - Take{iter: self, n: n} + Take{iter: self, n: n, consumed_back: 0} } /// Creates a new iterator which behaves in a similar fashion to foldl. @@ -762,6 +762,8 @@ impl<'a, A, T: ExactSize> ExactSize for Inspect<'a, A, T> {} impl> ExactSize for Rev {} impl<'a, A, B, T: ExactSize> ExactSize for Map<'a, A, B, T> {} impl, U: ExactSize> ExactSize<(A, B)> for Zip {} +impl> ExactSize for Skip {} +impl> ExactSize for Take {} /// An double-ended iterator with the direction inverted #[deriving(Clone)] @@ -1564,7 +1566,8 @@ impl<'a, A, T: Iterator> Iterator for TakeWhile<'a, A, T> { #[deriving(Clone)] pub struct Skip { priv iter: T, - priv n: uint + priv n: uint, + priv consumed_back: uint } impl> Iterator for Skip { @@ -1608,6 +1611,21 @@ impl> Iterator for Skip { } } +impl> DoubleEndedIterator for Skip { + #[inline] + fn next_back(&mut self) -> Option { + let (lower, upper) = self.iter.size_hint(); + assert_eq!(upper, Some(lower)); + + if lower >= self.n + self.consumed_back { + self.consumed_back += 1; + self.iter.next_back() + } else { + None + } + } +} + impl> RandomAccessIterator for Skip { #[inline] fn indexable(&self) -> uint { @@ -1628,7 +1646,8 @@ impl> RandomAccessIterator for Skip { #[deriving(Clone)] pub struct Take { priv iter: T, - priv n: uint + priv n: uint, + priv consumed_back: uint } impl> Iterator for Take { @@ -1657,6 +1676,20 @@ impl> Iterator for Take { } } +impl> DoubleEndedIterator for Take { + #[inline] + fn next_back(&mut self) -> Option { + let (lower, upper) = self.iter.size_hint(); + assert_eq!(upper, Some(lower)); + + while self.consumed_back + self.n < lower { + self.consumed_back += 1; + self.iter.next_back(); + } + self.iter.next_back() + } +} + impl> RandomAccessIterator for Take { #[inline] fn indexable(&self) -> uint { @@ -2792,6 +2825,36 @@ mod tests { assert_eq!(it.next_back(), None) } + #[test] + fn test_double_ended_skip() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut it = xs.iter().skip(3); + assert_eq!(it.next_back().unwrap(), &6); + assert_eq!(it.next_back().unwrap(), &5); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.next_back(), None); + + let mut it = xs.iter().skip(7); + assert_eq!(it.next_back(), None); + } + + #[test] + fn test_double_ended_take() { + let xs = [1, 2, 3, 4]; + let mut it = xs.iter().take(3); + assert_eq!(it.next_back().unwrap(), &3); + assert_eq!(it.next_back().unwrap(), &2); + assert_eq!(it.next_back().unwrap(), &1); + assert_eq!(it.next_back(), None); + + let mut it = xs.iter().take(7); + assert_eq!(it.next_back().unwrap(), &4); + assert_eq!(it.next_back().unwrap(), &3); + assert_eq!(it.next_back().unwrap(), &2); + assert_eq!(it.next_back().unwrap(), &1); + assert_eq!(it.next_back(), None); + } + #[test] fn test_rposition() { fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }