Skip to content

Commit 468cbd9

Browse files
committed
iterator: add a size_hint default method
also adds an implementation for the vector iterators
1 parent df166ba commit 468cbd9

File tree

2 files changed

+70
-6
lines changed

2 files changed

+70
-6
lines changed

src/libstd/iterator.rs

+49
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ implementing the `Iterator` trait.
1717
1818
*/
1919

20+
#[allow(default_methods)]; // solid enough for the use case here
21+
2022
use cmp;
2123
use iter::{FromIter, Times};
2224
use num::{Zero, One};
@@ -31,6 +33,12 @@ use clone::Clone;
3133
pub trait Iterator<A> {
3234
/// Advance the iterator and return the next value. Return `None` when the end is reached.
3335
fn next(&mut self) -> Option<A>;
36+
37+
/// Return a lower bound and upper bound on the remaining length of the iterator.
38+
///
39+
/// The common use case for the estimate is pre-allocating space to store the results.
40+
#[cfg(not(stage0))]
41+
fn size_hint(&self) -> (Option<uint>, Option<uint>) { (None, None) }
3442
}
3543

3644
/// 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> {
594602
self.b.next()
595603
}
596604
}
605+
606+
#[inline]
607+
#[cfg(not(stage0))]
608+
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
609+
let (a_lower, a_upper) = self.a.size_hint();
610+
let (b_lower, b_upper) = self.b.size_hint();
611+
612+
let lower = match (a_lower, b_lower) {
613+
(Some(x), Some(y)) => Some(x + y),
614+
(Some(x), None) => Some(x),
615+
(None, Some(y)) => Some(y),
616+
(None, None) => None
617+
};
618+
619+
let upper = match (a_upper, b_upper) {
620+
(Some(x), Some(y)) => Some(x + y),
621+
_ => None
622+
};
623+
624+
(lower, upper)
625+
}
597626
}
598627

599628
/// 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> {
627656
_ => None
628657
}
629658
}
659+
660+
#[inline]
661+
#[cfg(not(stage0))]
662+
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
663+
self.iter.size_hint()
664+
}
630665
}
631666

632667
/// 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> {
647682
}
648683
None
649684
}
685+
686+
#[inline]
687+
#[cfg(not(stage0))]
688+
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
689+
let (_, upper) = self.iter.size_hint();
690+
(None, upper) // can't know a lower bound, due to the predicate
691+
}
650692
}
651693

652694
/// 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,
666708
}
667709
None
668710
}
711+
712+
#[inline]
713+
#[cfg(not(stage0))]
714+
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
715+
let (_, upper) = self.iter.size_hint();
716+
(None, upper) // can't know a lower bound, due to the predicate
717+
}
669718
}
670719

671720
/// An iterator which yields the current count and the element during iteration

src/libstd/vec.rs

+21-6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use ptr::to_unsafe_ptr;
2929
use ptr;
3030
use ptr::RawPtr;
3131
use sys;
32+
use sys::size_of;
3233
use uint;
3334
use unstable::intrinsics;
3435
use vec;
@@ -2454,6 +2455,13 @@ macro_rules! iterator {
24542455
}
24552456
}
24562457
}
2458+
2459+
#[inline]
2460+
#[cfg(not(stage0))]
2461+
fn size_hint(&self) -> (Option<uint>, Option<uint>) {
2462+
let exact = Some(((self.end as uint) - (self.ptr as uint)) / size_of::<$elem>());
2463+
(exact, exact)
2464+
}
24572465
}
24582466
}
24592467
}
@@ -3909,16 +3917,23 @@ mod tests {
39093917
}
39103918

39113919
#[test]
3920+
#[cfg(not(stage0))]
39123921
fn test_iterator() {
39133922
use iterator::*;
39143923
let xs = [1, 2, 5, 10, 11];
3915-
let ys = [1, 2, 5, 10, 11, 19];
39163924
let mut it = xs.iter();
3917-
let mut i = 0;
3918-
for it.advance |&x| {
3919-
assert_eq!(x, ys[i]);
3920-
i += 1;
3921-
}
3925+
assert_eq!(it.size_hint(), (Some(5), Some(5)));
3926+
assert_eq!(it.next().unwrap(), &1);
3927+
assert_eq!(it.size_hint(), (Some(4), Some(4)));
3928+
assert_eq!(it.next().unwrap(), &2);
3929+
assert_eq!(it.size_hint(), (Some(3), Some(3)));
3930+
assert_eq!(it.next().unwrap(), &5);
3931+
assert_eq!(it.size_hint(), (Some(2), Some(2)));
3932+
assert_eq!(it.next().unwrap(), &10);
3933+
assert_eq!(it.size_hint(), (Some(1), Some(1)));
3934+
assert_eq!(it.next().unwrap(), &11);
3935+
assert_eq!(it.size_hint(), (Some(0), Some(0)));
3936+
assert!(it.next().is_none());
39223937
}
39233938

39243939
#[test]

0 commit comments

Comments
 (0)