diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 1d32c5df14ed9..7425da973688b 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -18,7 +18,7 @@ implementing the `Iterator` trait.
*/
use cmp;
-use num::{Zero, One, Integer, Saturating};
+use num::{Zero, One, Integer, CheckedAdd, Saturating};
use option::{Option, Some, None};
use ops::{Add, Mul, Sub};
use cmp::Ord;
@@ -817,7 +817,7 @@ impl, U: Iterator> Iterator for Chain {
let lower = a_lower.saturating_add(b_lower);
let upper = match (a_upper, b_upper) {
- (Some(x), Some(y)) => Some(x.saturating_add(y)),
+ (Some(x), Some(y)) => x.checked_add(&y),
_ => None
};
@@ -1094,6 +1094,21 @@ impl> Iterator for Peekable {
if self.peeked.is_some() { self.peeked.take() }
else { self.iter.next() }
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ let (lo, hi) = self.iter.size_hint();
+ if self.peeked.is_some() {
+ let lo = lo.saturating_add(1);
+ let hi = match hi {
+ Some(x) => x.checked_add(&1),
+ None => None
+ };
+ (lo, hi)
+ } else {
+ (lo, hi)
+ }
+ }
}
impl<'self, A, T: Iterator> Peekable {
@@ -1101,15 +1116,12 @@ impl<'self, A, T: Iterator> Peekable {
/// or None if the iterator is exhausted.
#[inline]
pub fn peek(&'self mut self) -> Option<&'self A> {
+ if self.peeked.is_none() {
+ self.peeked = self.iter.next();
+ }
match self.peeked {
Some(ref value) => Some(value),
- None => {
- self.peeked = self.iter.next();
- match self.peeked {
- Some(ref value) => Some(value),
- None => None,
- }
- },
+ None => None,
}
}
}
@@ -1355,7 +1367,7 @@ impl<'self, A, T: Iterator, B, U: Iterator> Iterator for
let (blo, bhi) = self.backiter.map_default((0, Some(0)), |it| it.size_hint());
let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
- ((0, Some(0)), Some(a), Some(b)) => (lo, Some(a.saturating_add(b))),
+ ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(&b)),
_ => (lo, None)
}
}
@@ -1461,6 +1473,12 @@ impl<'self, A, St> Iterator for Unfoldr<'self, A, St> {
fn next(&mut self) -> Option {
(self.f)(&mut self.state)
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ // no possible known bounds at this point
+ (0, None)
+ }
}
/// An infinite iterator starting at `start` and advancing by `step` with each
@@ -1504,6 +1522,9 @@ impl + Ord + Clone> Iterator for Range {
None
}
}
+
+ // FIXME: #8606 Implement size_hint() on Range
+ // Blocked on #8605 Need numeric trait for converting to `Option`
}
impl + Integer + Ord + Clone> DoubleEndedIterator for Range {
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 7c8046a64b2c2..e69cb1341bf9d 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -65,7 +65,7 @@ use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater};
use cmp;
use iterator::*;
use libc::c_void;
-use num::Zero;
+use num::{Integer, Zero, CheckedAdd, Saturating};
use option::{None, Option, Some};
use ptr::to_unsafe_ptr;
use ptr;
@@ -209,6 +209,7 @@ pub struct SplitIterator<'self, T> {
}
impl<'self, T> Iterator<&'self [T]> for SplitIterator<'self, T> {
+ #[inline]
fn next(&mut self) -> Option<&'self [T]> {
if self.finished { return None; }
@@ -230,6 +231,21 @@ impl<'self, T> Iterator<&'self [T]> for SplitIterator<'self, T> {
}
}
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ if self.finished {
+ return (0, Some(0))
+ }
+ // if the predicate doesn't match anything, we yield one slice
+ // if it matches every element, we yield N+1 empty slices where
+ // N is either the number of elements or the number of splits.
+ match (self.v.len(), self.n) {
+ (0,_) => (1, Some(1)),
+ (_,0) => (1, Some(1)),
+ (l,n) => (1, cmp::min(l,n).checked_add(&1u))
+ }
+ }
}
/// An iterator over the slices of a vector separated by elements that
@@ -242,6 +258,7 @@ pub struct RSplitIterator<'self, T> {
}
impl<'self, T> Iterator<&'self [T]> for RSplitIterator<'self, T> {
+ #[inline]
fn next(&mut self) -> Option<&'self [T]> {
if self.finished { return None; }
@@ -263,6 +280,18 @@ impl<'self, T> Iterator<&'self [T]> for RSplitIterator<'self, T> {
}
}
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ if self.finished {
+ return (0, Some(0))
+ }
+ match (self.v.len(), self.n) {
+ (0,_) => (1, Some(1)),
+ (_,0) => (1, Some(1)),
+ (l,n) => (1, cmp::min(l,n).checked_add(&1u))
+ }
+ }
}
// Appending
@@ -453,6 +482,7 @@ pub struct WindowIter<'self, T> {
}
impl<'self, T> Iterator<&'self [T]> for WindowIter<'self, T> {
+ #[inline]
fn next(&mut self) -> Option<&'self [T]> {
if self.size > self.v.len() {
None
@@ -462,6 +492,16 @@ impl<'self, T> Iterator<&'self [T]> for WindowIter<'self, T> {
ret
}
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ if self.size > self.v.len() {
+ (0, Some(0))
+ } else {
+ let x = self.v.len() - self.size;
+ (x.saturating_add(1), x.checked_add(&1u))
+ }
+ }
}
/// An iterator over a vector in (non-overlapping) chunks (`size`
@@ -476,6 +516,7 @@ pub struct ChunkIter<'self, T> {
}
impl<'self, T> Iterator<&'self [T]> for ChunkIter<'self, T> {
+ #[inline]
fn next(&mut self) -> Option<&'self [T]> {
if self.v.len() == 0 {
None
@@ -487,9 +528,21 @@ impl<'self, T> Iterator<&'self [T]> for ChunkIter<'self, T> {
Some(fst)
}
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ if self.v.len() == 0 {
+ (0, Some(0))
+ } else {
+ let (n, rem) = self.v.len().div_rem(&self.size);
+ let n = if rem > 0 { n+1 } else { n };
+ (n, Some(n))
+ }
+ }
}
impl<'self, T> DoubleEndedIterator<&'self [T]> for ChunkIter<'self, T> {
+ #[inline]
fn next_back(&mut self) -> Option<&'self [T]> {
if self.v.len() == 0 {
None
@@ -2223,6 +2276,7 @@ impl<'self, T> RandomAccessIterator<&'self T> for VecIterator<'self, T> {
exact
}
+ #[inline]
fn idx(&self, index: uint) -> Option<&'self T> {
unsafe {
if index < self.indexable() {
@@ -2268,6 +2322,7 @@ pub struct MoveIterator {
}
impl Iterator for MoveIterator {
+ #[inline]
fn next(&mut self) -> Option {
// this is peculiar, but is required for safety with respect
// to dtors. It traverses the first half of the vec, and
@@ -2285,6 +2340,12 @@ impl Iterator for MoveIterator {
self.v.pop_opt()
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ let l = self.v.len();
+ (l, Some(l))
+ }
}
/// An iterator that moves out of a vector in reverse order.
@@ -2294,9 +2355,16 @@ pub struct MoveRevIterator {
}
impl Iterator for MoveRevIterator {
+ #[inline]
fn next(&mut self) -> Option {
self.v.pop_opt()
}
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option) {
+ let l = self.v.len();
+ (l, Some(l))
+ }
}
impl FromIterator for ~[A] {