diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs index 3d1ca4a9818b6..1f7ba9f65303c 100644 --- a/src/libextra/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -186,6 +186,9 @@ pub struct PriorityQueueIterator <'self, T> { impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> { #[inline] fn next(&mut self) -> Option<(&'self T)> { self.iter.next() } + + #[inline] + fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } } #[cfg(test)] diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 5e898f8e59d9d..b7df27c0e4975 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -196,14 +196,15 @@ impl TreeMap { /// Get a lazy iterator over the key-value pairs in the map. /// Requires that it be frozen (immutable). pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> { - TreeMapIterator{stack: ~[], node: &self.root} + TreeMapIterator{stack: ~[], node: &self.root, remaining: self.length} } } /// Lazy forward iterator over a map pub struct TreeMapIterator<'self, K, V> { priv stack: ~[&'self ~TreeNode], - priv node: &'self Option<~TreeNode> + priv node: &'self Option<~TreeNode>, + priv remaining: uint } impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> { @@ -220,12 +221,18 @@ impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V None => { let res = self.stack.pop(); self.node = &res.right; + self.remaining -= 1; return Some((&res.key, &res.value)); } } } None } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (self.remaining, Some(self.remaining)) + } } impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> { diff --git a/src/librustc/util/enum_set.rs b/src/librustc/util/enum_set.rs index f9bd7a3508edb..3ce645e012b79 100644 --- a/src/librustc/util/enum_set.rs +++ b/src/librustc/util/enum_set.rs @@ -125,9 +125,9 @@ impl Iterator for EnumSetIterator { Some(elem) } - fn size_hint(&self) -> (Option, Option) { - let exact = Some(self.bits.population_count()); - (exact, exact) + fn size_hint(&self) -> (uint, Option) { + let exact = self.bits.population_count(); + (exact, Some(exact)) } } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 77befbf19aa92..b164bcbd28b3c 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -26,6 +26,7 @@ use option::{Option, Some, None}; use ops::{Add, Mul}; use cmp::Ord; use clone::Clone; +use uint; /// Conversion from an `Iterator` pub trait FromIterator> { @@ -43,7 +44,7 @@ pub trait Iterator { /// 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. - fn size_hint(&self) -> (Option, Option) { (None, None) } + fn size_hint(&self) -> (uint, Option) { (0, None) } } /// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also @@ -684,18 +685,18 @@ impl, U: Iterator> Iterator for ChainIterator { } #[inline] - fn size_hint(&self) -> (Option, Option) { + fn size_hint(&self) -> (uint, Option) { 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 lower = if uint::max_value - a_lower < b_lower { + uint::max_value + } else { + a_lower + b_lower }; let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value), (Some(x), Some(y)) => Some(x + y), _ => None }; @@ -719,6 +720,23 @@ impl, U: Iterator> Iterator<(A, B)> for ZipIterator None } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::min(x,y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None + }; + + (lower, upper) + } } /// An iterator which maps the values of `iter` with `f` @@ -737,7 +755,7 @@ impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { } #[inline] - fn size_hint(&self) -> (Option, Option) { + fn size_hint(&self) -> (uint, Option) { self.iter.size_hint() } } @@ -762,9 +780,9 @@ impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> { } #[inline] - fn size_hint(&self) -> (Option, Option) { + fn size_hint(&self) -> (uint, Option) { let (_, upper) = self.iter.size_hint(); - (None, upper) // can't know a lower bound, due to the predicate + (0, upper) // can't know a lower bound, due to the predicate } } @@ -787,9 +805,9 @@ impl<'self, A, B, T: Iterator> Iterator for FilterMapIterator<'self, A, B, } #[inline] - fn size_hint(&self) -> (Option, Option) { + fn size_hint(&self) -> (uint, Option) { let (_, upper) = self.iter.size_hint(); - (None, upper) // can't know a lower bound, due to the predicate + (0, upper) // can't know a lower bound, due to the predicate } } @@ -812,6 +830,11 @@ impl> Iterator<(uint, A)> for EnumerateIterator { _ => None } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + self.iter.size_hint() + } } /// An iterator which rejects elements while `predicate` is true @@ -844,6 +867,12 @@ impl<'self, A, T: Iterator> Iterator for SkipWhileIterator<'self, A, T> { } } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } /// An iterator which only accepts elements while `predicate` is true @@ -872,6 +901,12 @@ impl<'self, A, T: Iterator> Iterator for TakeWhileIterator<'self, A, T> { } } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } /// An iterator which skips over `n` elements of `iter`. @@ -905,6 +940,21 @@ impl> Iterator for SkipIterator { next } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (lower, upper) = self.iter.size_hint(); + + let lower = if lower >= self.n { lower - self.n } else { 0 }; + + let upper = match upper { + Some(x) if x >= self.n => Some(x - self.n), + Some(_) => Some(0), + None => None + }; + + (lower, upper) + } } /// An iterator which only iterates over the first `n` iterations of `iter`. @@ -925,6 +975,20 @@ impl> Iterator for TakeIterator { None } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (lower, upper) = self.iter.size_hint(); + + let lower = cmp::min(lower, self.n); + + let upper = match upper { + Some(x) if x < self.n => Some(x), + _ => Some(self.n) + }; + + (lower, upper) + } } /// An iterator to maintain state while iterating another iterator @@ -941,6 +1005,12 @@ impl<'self, A, B, T: Iterator, St> Iterator for ScanIterator<'self, A, B, fn next(&mut self) -> Option { self.iter.next().chain(|a| (self.f)(&mut self.state, a)) } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the scan function + } } /// An iterator that maps each element to an iterator, @@ -1022,6 +1092,11 @@ impl + Clone> Iterator for Counter { self.state = self.state.add(&self.step); // FIXME: #6050 Some(result) } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + (uint::max_value, None) // Too bad we can't specify an infinite lower bound + } } #[cfg(test)] @@ -1237,6 +1312,43 @@ mod tests { assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None); } + #[test] + fn test_iterator_size_hint() { + let c = Counter::new(0, 1); + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + let v2 = &[10, 11, 12]; + let vi = v.iter(); + + assert_eq!(c.size_hint(), (uint::max_value, None)); + assert_eq!(vi.size_hint(), (10, Some(10))); + + assert_eq!(c.take_(5).size_hint(), (5, Some(5))); + assert_eq!(c.skip(5).size_hint().second(), None); + assert_eq!(c.take_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.skip_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.enumerate().size_hint(), (uint::max_value, None)); + assert_eq!(c.chain_(vi.transform(|&i| i)).size_hint(), (uint::max_value, None)); + assert_eq!(c.zip(vi).size_hint(), (10, Some(10))); + assert_eq!(c.scan(0, |_,_| Some(0)).size_hint(), (0, None)); + assert_eq!(c.filter(|_| false).size_hint(), (0, None)); + assert_eq!(c.transform(|_| 0).size_hint(), (uint::max_value, None)); + assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); + + assert_eq!(vi.take_(5).size_hint(), (5, Some(5))); + assert_eq!(vi.take_(12).size_hint(), (10, Some(10))); + assert_eq!(vi.skip(3).size_hint(), (7, Some(7))); + assert_eq!(vi.skip(12).size_hint(), (0, Some(0))); + assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.enumerate().size_hint(), (10, Some(10))); + assert_eq!(vi.chain_(v2.iter()).size_hint(), (13, Some(13))); + assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3))); + assert_eq!(vi.scan(0, |_,_| Some(0)).size_hint(), (0, Some(10))); + assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10))); + assert_eq!(vi.transform(|i| i+1).size_hint(), (10, Some(10))); + assert_eq!(vi.filter_map(|_| Some(0)).size_hint(), (0, Some(10))); + } + #[test] fn test_collect() { let a = ~[1, 2, 3, 4, 5]; diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 1014ff48b1d23..7244a9a7aac54 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2024,14 +2024,14 @@ macro_rules! iterator { } #[inline] - fn size_hint(&self) -> (Option, Option) { + fn size_hint(&self) -> (uint, Option) { let diff = if $step > 0 { (self.end as uint) - (self.ptr as uint) } else { (self.ptr as uint) - (self.end as uint) }; - let exact = Some(diff / size_of::<$elem>()); - (exact, exact) + let exact = diff / size_of::<$elem>(); + (exact, Some(exact)) } } } @@ -2132,7 +2132,7 @@ impl> FromIterator for ~[A] { impl> FromIterator for ~[A] { pub fn from_iterator(iterator: &mut T) -> ~[A] { let (lower, _) = iterator.size_hint(); - let mut xs = with_capacity(lower.get_or_zero()); + let mut xs = with_capacity(lower); for iterator.advance |x| { xs.push(x); } @@ -2968,17 +2968,17 @@ mod tests { use iterator::*; let xs = [1, 2, 5, 10, 11]; let mut it = xs.iter(); - assert_eq!(it.size_hint(), (Some(5), Some(5))); + assert_eq!(it.size_hint(), (5, Some(5))); assert_eq!(it.next().unwrap(), &1); - assert_eq!(it.size_hint(), (Some(4), Some(4))); + assert_eq!(it.size_hint(), (4, Some(4))); assert_eq!(it.next().unwrap(), &2); - assert_eq!(it.size_hint(), (Some(3), Some(3))); + assert_eq!(it.size_hint(), (3, Some(3))); assert_eq!(it.next().unwrap(), &5); - assert_eq!(it.size_hint(), (Some(2), Some(2))); + assert_eq!(it.size_hint(), (2, Some(2))); assert_eq!(it.next().unwrap(), &10); - assert_eq!(it.size_hint(), (Some(1), Some(1))); + assert_eq!(it.size_hint(), (1, Some(1))); assert_eq!(it.next().unwrap(), &11); - assert_eq!(it.size_hint(), (Some(0), Some(0))); + assert_eq!(it.size_hint(), (0, Some(0))); assert!(it.next().is_none()); } @@ -2986,10 +2986,10 @@ mod tests { fn test_iter_size_hints() { use iterator::*; let mut xs = [1, 2, 5, 10, 11]; - assert_eq!(xs.iter().size_hint(), (Some(5), Some(5))); - assert_eq!(xs.rev_iter().size_hint(), (Some(5), Some(5))); - assert_eq!(xs.mut_iter().size_hint(), (Some(5), Some(5))); - assert_eq!(xs.mut_rev_iter().size_hint(), (Some(5), Some(5))); + assert_eq!(xs.iter().size_hint(), (5, Some(5))); + assert_eq!(xs.rev_iter().size_hint(), (5, Some(5))); + assert_eq!(xs.mut_iter().size_hint(), (5, Some(5))); + assert_eq!(xs.mut_rev_iter().size_hint(), (5, Some(5))); } #[test] diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index bf8c5ae462bf0..8e2da3d6eb1aa 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -146,4 +146,12 @@ impl<'self, T> Iterator<&'self T> for OptVecIterator<'self, T> { None => None } } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + match self.iter { + Some(ref x) => x.size_hint(), + None => (0, Some(0)) + } + } }