diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2013-06-21 06:12:01 -0400 |
|---|---|---|
| committer | Daniel Micay <danielmicay@gmail.com> | 2013-06-22 15:59:59 -0400 |
| commit | 468cbd9d014d4f8610694057f1a8132f1eaf0b19 (patch) | |
| tree | 423324451ff92511df46bd9a82886ed4bbe164fc /src/libstd | |
| parent | df166bae1ff583b39b4046becc87d28c9f90094b (diff) | |
| download | rust-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.rs | 49 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 27 |
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] |
