about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorblake2-ppc <blake2-ppc>2013-09-30 20:59:46 +0200
committerblake2-ppc <blake2-ppc>2013-09-30 20:59:46 +0200
commit8163cb53903dd09e920b6267eba72793394b77d0 (patch)
treeb68d1c18f17c947a08af5dcd462fac572474909c /src/libstd
parent92e7bb67a8038ff73ad9dc88d8be3d3df4777282 (diff)
downloadrust-8163cb53903dd09e920b6267eba72793394b77d0.tar.gz
rust-8163cb53903dd09e920b6267eba72793394b77d0.zip
std::iter: Introduce .by_ref() adaptor
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::

   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));
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/iter.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
index 4695123548b..255f869a905 100644
--- a/src/libstd/iter.rs
+++ b/src/libstd/iter.rs
@@ -405,6 +405,25 @@ pub trait Iterator<A> {
         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<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterato
     }
 }
 
+/// A mutable reference to an iterator
+pub struct ByRef<'self, T> {
+    priv iter: &'self mut T
+}
+
+impl<'self, A, T: Iterator<A>> Iterator<A> for ByRef<'self, T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> { self.iter.next() }
+    // FIXME: #9629 we cannot implement &self methods like size_hint on ByRef
+}
+
+impl<'self, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for ByRef<'self, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<A> { self.iter.next_back() }
+}
+
 /// A trait for iterators over elements which can be added together
 pub trait AdditiveIterator<A> {
     /// Iterates over the entire iterator, summing up all the elements
@@ -2501,6 +2536,15 @@ mod tests {
     }
 
     #[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];
         let mut it = xs.iter();