From c98f0cb3627fbdc2f1e56cfe1aad20a96730d208 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Wed, 17 Apr 2013 19:34:53 -0400
Subject: [PATCH] vec: add an external iterator

---
 src/libcore/vec.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 30201304d6191..0403ae64f0205 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -18,6 +18,10 @@ use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
 use clone::Clone;
 use iter::BaseIter;
 use iter;
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+use iterator::Iterator;
 use kinds::Copy;
 use libc;
 use option::{None, Option, Some};
@@ -1919,6 +1923,7 @@ impl<'self,T> ImmutableVector<T> for &'self [T] {
 #[cfg(stage3)]
 pub trait ImmutableVector<'self, T> {
     fn slice(&self, start: uint, end: uint) -> &'self [T];
+    fn iter(self) -> VecIterator<'self, T>;
     fn head(&self) -> &'self T;
     fn head_opt(&self) -> Option<&'self T>;
     fn tail(&self) -> &'self [T];
@@ -1949,6 +1954,15 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
         slice(*self, start, end)
     }
 
+    #[inline]
+    fn iter(self) -> VecIterator<'self, T> {
+        unsafe {
+            let p = vec::raw::to_ptr(self);
+            VecIterator{ptr: p, end: p.offset(self.len()),
+                        lifetime: cast::transmute(p)}
+        }
+    }
+
     /// Returns the first element of a vector, failing if the vector is empty.
     #[inline]
     fn head(&self) -> &'self T { head(*self) }
@@ -2795,7 +2809,33 @@ impl<A:Clone> Clone for ~[A] {
     }
 }
 
-// ___________________________________________________________________________
+// could be implemented with &[T] with .slice(), but this avoids bounds checks
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+pub struct VecIterator<'self, T> {
+    priv ptr: *T,
+    priv end: *T,
+    priv lifetime: &'self T // FIXME: #5922
+}
+
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> {
+    #[inline]
+    fn next(&mut self) -> Option<&'self T> {
+        unsafe {
+            if self.ptr == self.end {
+                None
+            } else {
+                let old = self.ptr;
+                self.ptr = self.ptr.offset(1);
+                Some(cast::transmute(old))
+            }
+        }
+    }
+}
 
 #[cfg(test)]
 mod tests {
@@ -4421,6 +4461,19 @@ mod tests {
         [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less;
         [2, 2].cmp(& &[1, 2, 3, 4]) == Greater;
     }
+
+    #[test]
+    fn test_iterator() {
+        use iterator::*;
+        let xs = [1, 2, 5, 10, 11];
+        let ys = [1, 2, 5, 10, 11, 19];
+        let mut it = xs.iter();
+        let mut i = 0;
+        for it.advance |&x| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+    }
 }
 
 // Local Variables: