iterator: add a size_hint default method
also adds an implementation for the vector iterators
This commit is contained in:
parent
df166bae1f
commit
468cbd9d01
@ -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
|
||||
|
@ -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]
|
||||
|
Loading…
x
Reference in New Issue
Block a user