diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
index 4695123548bd9..255f869a9056c 100644
--- a/src/libstd/iter.rs
+++ b/src/libstd/iter.rs
@@ -405,6 +405,25 @@ pub trait Iterator {
Inspect{iter: self, f: f}
}
+ /// Creates a wrapper around a mutable reference to the iterator.
+ ///
+ /// This is useful to allow applying iterator adaptors while still
+ /// retaining ownership of the original iterator value.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let mut xs = range(0, 10);
+ /// // sum the first five values
+ /// let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
+ /// assert!(partial_sum == 10);
+ /// // xs.next() is now `5`
+ /// assert!(xs.next() == Some(5));
+ /// ```
+ fn by_ref<'r>(&'r mut self) -> ByRef<'r, Self> {
+ ByRef{iter: self}
+ }
+
/// An adaptation of an external iterator to the for-loop protocol of rust.
///
/// # Example
@@ -771,6 +790,22 @@ impl + RandomAccessIterator> RandomAccessIterato
}
}
+/// A mutable reference to an iterator
+pub struct ByRef<'self, T> {
+ priv iter: &'self mut T
+}
+
+impl<'self, A, T: Iterator> Iterator for ByRef<'self, T> {
+ #[inline]
+ fn next(&mut self) -> Option { self.iter.next() }
+ // FIXME: #9629 we cannot implement &self methods like size_hint on ByRef
+}
+
+impl<'self, A, T: DoubleEndedIterator> DoubleEndedIterator for ByRef<'self, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option { self.iter.next_back() }
+}
+
/// A trait for iterators over elements which can be added together
pub trait AdditiveIterator {
/// Iterates over the entire iterator, summing up all the elements
@@ -2500,6 +2535,15 @@ mod tests {
assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
}
+ #[test]
+ fn test_by_ref() {
+ let mut xs = range(0, 10);
+ // sum the first five values
+ let partial_sum = xs.by_ref().take(5).fold(0, |a, b| a + b);
+ assert_eq!(partial_sum, 10);
+ assert_eq!(xs.next(), Some(5));
+ }
+
#[test]
fn test_invert() {
let xs = [2, 4, 6, 8, 10, 12, 14, 16];