]> git.lizzy.rs Git - rust.git/commitdiff
iterator: Add .cycle() to repeat an iterator
authorblake2-ppc <blake2-ppc>
Thu, 18 Jul 2013 15:09:08 +0000 (17:09 +0200)
committerblake2-ppc <blake2-ppc>
Sat, 20 Jul 2013 18:22:48 +0000 (20:22 +0200)
src/libstd/iterator.rs

index c8cde69197b237984762548dff2abf915f2b1b59..13c234d63974cb8f60d7a1e4d85b940a0d5e15f2 100644 (file)
@@ -729,6 +729,55 @@ fn min(&mut self) -> Option<A> {
     }
 }
 
+/// A trait for iterators that are clonable.
+// FIXME #6967: Dummy A parameter to get around type inference bug
+pub trait ClonableIterator<A> {
+    /// Repeats an iterator endlessly
+    ///
+    /// # Example
+    ///
+    /// ~~~ {.rust}
+    /// let a = Counter::new(1,1).take_(1);
+    /// let mut cy = a.cycle();
+    /// assert_eq!(cy.next(), Some(1));
+    /// assert_eq!(cy.next(), Some(1));
+    /// ~~~
+    fn cycle(self) -> CycleIterator<A, Self>;
+}
+
+impl<A, T: Clone + Iterator<A>> ClonableIterator<A> for T {
+    #[inline]
+    fn cycle(self) -> CycleIterator<A, T> {
+        CycleIterator{orig: self.clone(), iter: self}
+    }
+}
+
+/// An iterator that repeats endlessly
+pub struct CycleIterator<A, T> {
+    priv orig: T,
+    priv iter: T,
+}
+
+impl<A, T: Clone + Iterator<A>> Iterator<A> for CycleIterator<A, T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        match self.iter.next() {
+            None => { self.iter = self.orig.clone(); self.iter.next() }
+            y => y
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        // the cycle iterator is either empty or infinite
+        match self.orig.size_hint() {
+            sz @ (0, Some(0)) => sz,
+            (0, _) => (0, None),
+            _ => (uint::max_value, None)
+        }
+    }
+}
+
 /// An iterator which strings two iterators together
 // FIXME #6967: Dummy A parameter to get around type inference bug
 pub struct ChainIterator<A, T, U> {