Skip to content

Commit 20016b9

Browse files
committed
Implement .size_hint() on the remaining Iterator adaptors
Every iterator adaptor now has an implementation of .size_hint() that makes sense, except for when the default of (0, None) is correct.
1 parent dc9b3ff commit 20016b9

File tree

1 file changed

+118
-1
lines changed

1 file changed

+118
-1
lines changed

src/libstd/iterator.rs

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use option::{Option, Some, None};
2626
use ops::{Add, Mul};
2727
use cmp::Ord;
2828
use clone::Clone;
29+
use uint;
2930

3031
/// Conversion from an `Iterator`
3132
pub trait FromIterator<A, T: Iterator<A>> {
@@ -688,9 +689,14 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<A, T, U> {
688689
let (a_lower, a_upper) = self.a.size_hint();
689690
let (b_lower, b_upper) = self.b.size_hint();
690691

691-
let lower = a_lower + b_lower;
692+
let lower = if uint::max_value - a_lower < b_lower {
693+
uint::max_value
694+
} else {
695+
a_lower + b_lower
696+
};
692697

693698
let upper = match (a_upper, b_upper) {
699+
(Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value),
694700
(Some(x), Some(y)) => Some(x + y),
695701
_ => None
696702
};
@@ -714,6 +720,23 @@ impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<A, T
714720
_ => None
715721
}
716722
}
723+
724+
#[inline]
725+
fn size_hint(&self) -> (uint, Option<uint>) {
726+
let (a_lower, a_upper) = self.a.size_hint();
727+
let (b_lower, b_upper) = self.b.size_hint();
728+
729+
let lower = cmp::min(a_lower, b_lower);
730+
731+
let upper = match (a_upper, b_upper) {
732+
(Some(x), Some(y)) => Some(cmp::min(x,y)),
733+
(Some(x), None) => Some(x),
734+
(None, Some(y)) => Some(y),
735+
(None, None) => None
736+
};
737+
738+
(lower, upper)
739+
}
717740
}
718741

719742
/// An iterator which maps the values of `iter` with `f`
@@ -807,6 +830,11 @@ impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<A, T> {
807830
_ => None
808831
}
809832
}
833+
834+
#[inline]
835+
fn size_hint(&self) -> (uint, Option<uint>) {
836+
self.iter.size_hint()
837+
}
810838
}
811839

812840
/// An iterator which rejects elements while `predicate` is true
@@ -839,6 +867,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> {
839867
}
840868
}
841869
}
870+
871+
#[inline]
872+
fn size_hint(&self) -> (uint, Option<uint>) {
873+
let (_, upper) = self.iter.size_hint();
874+
(0, upper) // can't know a lower bound, due to the predicate
875+
}
842876
}
843877

844878
/// An iterator which only accepts elements while `predicate` is true
@@ -867,6 +901,12 @@ impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> {
867901
}
868902
}
869903
}
904+
905+
#[inline]
906+
fn size_hint(&self) -> (uint, Option<uint>) {
907+
let (_, upper) = self.iter.size_hint();
908+
(0, upper) // can't know a lower bound, due to the predicate
909+
}
870910
}
871911

872912
/// An iterator which skips over `n` elements of `iter`.
@@ -900,6 +940,21 @@ impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<A, T> {
900940
next
901941
}
902942
}
943+
944+
#[inline]
945+
fn size_hint(&self) -> (uint, Option<uint>) {
946+
let (lower, upper) = self.iter.size_hint();
947+
948+
let lower = if lower >= self.n { lower - self.n } else { 0 };
949+
950+
let upper = match upper {
951+
Some(x) if x >= self.n => Some(x - self.n),
952+
Some(_) => Some(0),
953+
None => None
954+
};
955+
956+
(lower, upper)
957+
}
903958
}
904959

905960
/// An iterator which only iterates over the first `n` iterations of `iter`.
@@ -920,6 +975,20 @@ impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<A, T> {
920975
None
921976
}
922977
}
978+
979+
#[inline]
980+
fn size_hint(&self) -> (uint, Option<uint>) {
981+
let (lower, upper) = self.iter.size_hint();
982+
983+
let lower = cmp::min(lower, self.n);
984+
985+
let upper = match upper {
986+
Some(x) if x < self.n => Some(x),
987+
_ => Some(self.n)
988+
};
989+
990+
(lower, upper)
991+
}
923992
}
924993

925994
/// An iterator to maintain state while iterating another iterator
@@ -936,6 +1005,12 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B,
9361005
fn next(&mut self) -> Option<B> {
9371006
self.iter.next().chain(|a| (self.f)(&mut self.state, a))
9381007
}
1008+
1009+
#[inline]
1010+
fn size_hint(&self) -> (uint, Option<uint>) {
1011+
let (_, upper) = self.iter.size_hint();
1012+
(0, upper) // can't know a lower bound, due to the scan function
1013+
}
9391014
}
9401015

9411016
/// An iterator that maps each element to an iterator,
@@ -1017,6 +1092,11 @@ impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
10171092
self.state = self.state.add(&self.step); // FIXME: #6050
10181093
Some(result)
10191094
}
1095+
1096+
#[inline]
1097+
fn size_hint(&self) -> (uint, Option<uint>) {
1098+
(uint::max_value, None) // Too bad we can't specify an infinite lower bound
1099+
}
10201100
}
10211101

10221102
#[cfg(test)]
@@ -1232,6 +1312,43 @@ mod tests {
12321312
assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None);
12331313
}
12341314

1315+
#[test]
1316+
fn test_iterator_size_hint() {
1317+
let c = Counter::new(0, 1);
1318+
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
1319+
let v2 = &[10, 11, 12];
1320+
let vi = v.iter();
1321+
1322+
assert_eq!(c.size_hint(), (uint::max_value, None));
1323+
assert_eq!(vi.size_hint(), (10, Some(10)));
1324+
1325+
assert_eq!(c.take_(5).size_hint(), (5, Some(5)));
1326+
assert_eq!(c.skip(5).size_hint().second(), None);
1327+
assert_eq!(c.take_while(|_| false).size_hint(), (0, None));
1328+
assert_eq!(c.skip_while(|_| false).size_hint(), (0, None));
1329+
assert_eq!(c.enumerate().size_hint(), (uint::max_value, None));
1330+
assert_eq!(c.chain_(vi.transform(|&i| i)).size_hint(), (uint::max_value, None));
1331+
assert_eq!(c.zip(vi).size_hint(), (10, Some(10)));
1332+
assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None));
1333+
assert_eq!(c.filter(|_| false).size_hint(), (0, None));
1334+
assert_eq!(c.transform(|_| 0).size_hint(), (uint::max_value, None));
1335+
assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
1336+
1337+
assert_eq!(vi.take_(5).size_hint(), (5, Some(5)));
1338+
assert_eq!(vi.take_(12).size_hint(), (10, Some(10)));
1339+
assert_eq!(vi.skip(3).size_hint(), (7, Some(7)));
1340+
assert_eq!(vi.skip(12).size_hint(), (0, Some(0)));
1341+
assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10)));
1342+
assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10)));
1343+
assert_eq!(vi.enumerate().size_hint(), (10, Some(10)));
1344+
assert_eq!(vi.chain_(v2.iter()).size_hint(), (13, Some(13)));
1345+
assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3)));
1346+
assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10)));
1347+
assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10)));
1348+
assert_eq!(vi.transform(|i| i+1).size_hint(), (10, Some(10)));
1349+
assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10)));
1350+
}
1351+
12351352
#[test]
12361353
fn test_collect() {
12371354
let a = ~[1, 2, 3, 4, 5];

0 commit comments

Comments
 (0)