about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-06-21 06:12:01 -0400
committerDaniel Micay <danielmicay@gmail.com>2013-06-22 15:59:59 -0400
commit468cbd9d014d4f8610694057f1a8132f1eaf0b19 (patch)
tree423324451ff92511df46bd9a82886ed4bbe164fc /src/libstd
parentdf166bae1ff583b39b4046becc87d28c9f90094b (diff)
downloadrust-468cbd9d014d4f8610694057f1a8132f1eaf0b19.tar.gz
rust-468cbd9d014d4f8610694057f1a8132f1eaf0b19.zip
iterator: add a size_hint default method
also adds an implementation for the vector iterators
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/iterator.rs49
-rw-r--r--src/libstd/vec.rs27
2 files changed, 70 insertions, 6 deletions
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 394066f1d4c..fa27f4560c1 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -17,6 +17,8 @@ implementing the `Iterator` trait.
 
 */
 
+#[allow(default_methods)]; // solid enough for the use case here
+
 use cmp;
 use iter::{FromIter, Times};
 use num::{Zero, One};
@@ -31,6 +33,12 @@ use clone::Clone;
 pub trait Iterator<A> {
     /// Advance the iterator and return the next value. Return `None` when the end is reached.
     fn next(&mut self) -> Option<A>;
+
+    /// Return a lower bound and upper bound on the remaining length of the iterator.
+    ///
+    /// The common use case for the estimate is pre-allocating space to store the results.
+    #[cfg(not(stage0))]
+    fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) }
 }
 
 /// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
@@ -594,6 +602,27 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
             self.b.next()
         }
     }
+
+    #[inline]
+    #[cfg(not(stage0))]
+    fn size_hint(&self) -> (Option<uint>, Option<uint>) {
+        let (a_lower, a_upper) = self.a.size_hint();
+        let (b_lower, b_upper) = self.b.size_hint();
+
+        let lower = match (a_lower, b_lower) {
+            (Some(x), Some(y)) => Some(x + y),
+            (Some(x), None) => Some(x),
+            (None, Some(y)) => Some(y),
+            (None, None) => None
+        };
+
+        let upper = match (a_upper, b_upper) {
+            (Some(x), Some(y)) => Some(x + y),
+            _ => None
+        };
+
+        (lower, upper)
+    }
 }
 
 /// An iterator which iterates two other iterators simultaneously
@@ -627,6 +656,12 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
             _ => None
         }
     }
+
+    #[inline]
+    #[cfg(not(stage0))]
+    fn size_hint(&self) -> (Option<uint>, Option<uint>) {
+        self.iter.size_hint()
+    }
 }
 
 /// An iterator which filters the elements of `iter` with `predicate`
@@ -647,6 +682,13 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
         }
         None
     }
+
+    #[inline]
+    #[cfg(not(stage0))]
+    fn size_hint(&self) -> (Option<uint>, Option<uint>) {
+        let (_, upper) = self.iter.size_hint();
+        (None, upper) // can't know a lower bound, due to the predicate
+    }
 }
 
 /// An iterator which uses `f` to both filter and map elements from `iter`
@@ -666,6 +708,13 @@ impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B,
         }
         None
     }
+
+    #[inline]
+    #[cfg(not(stage0))]
+    fn size_hint(&self) -> (Option<uint>, Option<uint>) {
+        let (_, upper) = self.iter.size_hint();
+        (None, upper) // can't know a lower bound, due to the predicate
+    }
 }
 
 /// An iterator which yields the current count and the element during iteration
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 703224e37c5..b03b6efcaaf 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -29,6 +29,7 @@ use ptr::to_unsafe_ptr;
 use ptr;
 use ptr::RawPtr;
 use sys;
+use sys::size_of;
 use uint;
 use unstable::intrinsics;
 use vec;
@@ -2454,6 +2455,13 @@ macro_rules! iterator {
                     }
                 }
             }
+
+            #[inline]
+            #[cfg(not(stage0))]
+            fn size_hint(&self) -> (Option<uint>, Option<uint>) {
+                let exact = Some(((self.end as uint) - (self.ptr as uint)) / size_of::<$elem>());
+                (exact, exact)
+            }
         }
     }
 }
@@ -3909,16 +3917,23 @@ mod tests {
     }
 
     #[test]
+    #[cfg(not(stage0))]
     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;
-        }
+        assert_eq!(it.size_hint(), (Some(5), Some(5)));
+        assert_eq!(it.next().unwrap(), &1);
+        assert_eq!(it.size_hint(), (Some(4), Some(4)));
+        assert_eq!(it.next().unwrap(), &2);
+        assert_eq!(it.size_hint(), (Some(3), Some(3)));
+        assert_eq!(it.next().unwrap(), &5);
+        assert_eq!(it.size_hint(), (Some(2), Some(2)));
+        assert_eq!(it.next().unwrap(), &10);
+        assert_eq!(it.size_hint(), (Some(1), Some(1)));
+        assert_eq!(it.next().unwrap(), &11);
+        assert_eq!(it.size_hint(), (Some(0), Some(0)));
+        assert!(it.next().is_none());
     }
 
     #[test]