Skip to content

Commit bf90634

Browse files
committed
auto merge of #8604 : kballard/rust/iter-size-hint, r=graydon
Implement `size_hint()` on the new std::vec Iterators. Add or update `size_hint()` on std::iterator Iterators where appropriate. r? @thestinger
2 parents 9765f33 + 8741770 commit bf90634

File tree

2 files changed

+100
-11
lines changed

2 files changed

+100
-11
lines changed

src/libstd/iterator.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ implementing the `Iterator` trait.
1818
*/
1919

2020
use cmp;
21-
use num::{Zero, One, Integer, Saturating};
21+
use num::{Zero, One, Integer, CheckedAdd, Saturating};
2222
use option::{Option, Some, None};
2323
use ops::{Add, Mul, Sub};
2424
use cmp::Ord;
@@ -838,7 +838,7 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for Chain<T, U> {
838838
let lower = a_lower.saturating_add(b_lower);
839839

840840
let upper = match (a_upper, b_upper) {
841-
(Some(x), Some(y)) => Some(x.saturating_add(y)),
841+
(Some(x), Some(y)) => x.checked_add(&y),
842842
_ => None
843843
};
844844

@@ -1115,22 +1115,34 @@ impl<A, T: Iterator<A>> Iterator<A> for Peekable<A, T> {
11151115
if self.peeked.is_some() { self.peeked.take() }
11161116
else { self.iter.next() }
11171117
}
1118+
1119+
#[inline]
1120+
fn size_hint(&self) -> (uint, Option<uint>) {
1121+
let (lo, hi) = self.iter.size_hint();
1122+
if self.peeked.is_some() {
1123+
let lo = lo.saturating_add(1);
1124+
let hi = match hi {
1125+
Some(x) => x.checked_add(&1),
1126+
None => None
1127+
};
1128+
(lo, hi)
1129+
} else {
1130+
(lo, hi)
1131+
}
1132+
}
11181133
}
11191134

11201135
impl<'self, A, T: Iterator<A>> Peekable<A, T> {
11211136
/// Return a reference to the next element of the iterator with out advancing it,
11221137
/// or None if the iterator is exhausted.
11231138
#[inline]
11241139
pub fn peek(&'self mut self) -> Option<&'self A> {
1140+
if self.peeked.is_none() {
1141+
self.peeked = self.iter.next();
1142+
}
11251143
match self.peeked {
11261144
Some(ref value) => Some(value),
1127-
None => {
1128-
self.peeked = self.iter.next();
1129-
match self.peeked {
1130-
Some(ref value) => Some(value),
1131-
None => None,
1132-
}
1133-
},
1145+
None => None,
11341146
}
11351147
}
11361148
}
@@ -1376,7 +1388,7 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
13761388
let (blo, bhi) = self.backiter.map_default((0, Some(0)), |it| it.size_hint());
13771389
let lo = flo.saturating_add(blo);
13781390
match (self.iter.size_hint(), fhi, bhi) {
1379-
((0, Some(0)), Some(a), Some(b)) => (lo, Some(a.saturating_add(b))),
1391+
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(&b)),
13801392
_ => (lo, None)
13811393
}
13821394
}
@@ -1482,6 +1494,12 @@ impl<'self, A, St> Iterator<A> for Unfoldr<'self, A, St> {
14821494
fn next(&mut self) -> Option<A> {
14831495
(self.f)(&mut self.state)
14841496
}
1497+
1498+
#[inline]
1499+
fn size_hint(&self) -> (uint, Option<uint>) {
1500+
// no possible known bounds at this point
1501+
(0, None)
1502+
}
14851503
}
14861504

14871505
/// An infinite iterator starting at `start` and advancing by `step` with each
@@ -1525,6 +1543,9 @@ impl<A: Add<A, A> + Ord + Clone> Iterator<A> for Range<A> {
15251543
None
15261544
}
15271545
}
1546+
1547+
// FIXME: #8606 Implement size_hint() on Range
1548+
// Blocked on #8605 Need numeric trait for converting to `Option<uint>`
15281549
}
15291550

15301551
impl<A: Sub<A, A> + Integer + Ord + Clone> DoubleEndedIterator<A> for Range<A> {

src/libstd/vec.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater};
6565
use cmp;
6666
use iterator::*;
6767
use libc::c_void;
68-
use num::Zero;
68+
use num::{Integer, Zero, CheckedAdd, Saturating};
6969
use option::{None, Option, Some};
7070
use ptr::to_unsafe_ptr;
7171
use ptr;
@@ -209,6 +209,7 @@ pub struct SplitIterator<'self, T> {
209209
}
210210

211211
impl<'self, T> Iterator<&'self [T]> for SplitIterator<'self, T> {
212+
#[inline]
212213
fn next(&mut self) -> Option<&'self [T]> {
213214
if self.finished { return None; }
214215

@@ -230,6 +231,21 @@ impl<'self, T> Iterator<&'self [T]> for SplitIterator<'self, T> {
230231
}
231232
}
232233
}
234+
235+
#[inline]
236+
fn size_hint(&self) -> (uint, Option<uint>) {
237+
if self.finished {
238+
return (0, Some(0))
239+
}
240+
// if the predicate doesn't match anything, we yield one slice
241+
// if it matches every element, we yield N+1 empty slices where
242+
// N is either the number of elements or the number of splits.
243+
match (self.v.len(), self.n) {
244+
(0,_) => (1, Some(1)),
245+
(_,0) => (1, Some(1)),
246+
(l,n) => (1, cmp::min(l,n).checked_add(&1u))
247+
}
248+
}
233249
}
234250

235251
/// An iterator over the slices of a vector separated by elements that
@@ -242,6 +258,7 @@ pub struct RSplitIterator<'self, T> {
242258
}
243259

244260
impl<'self, T> Iterator<&'self [T]> for RSplitIterator<'self, T> {
261+
#[inline]
245262
fn next(&mut self) -> Option<&'self [T]> {
246263
if self.finished { return None; }
247264

@@ -263,6 +280,18 @@ impl<'self, T> Iterator<&'self [T]> for RSplitIterator<'self, T> {
263280
}
264281
}
265282
}
283+
284+
#[inline]
285+
fn size_hint(&self) -> (uint, Option<uint>) {
286+
if self.finished {
287+
return (0, Some(0))
288+
}
289+
match (self.v.len(), self.n) {
290+
(0,_) => (1, Some(1)),
291+
(_,0) => (1, Some(1)),
292+
(l,n) => (1, cmp::min(l,n).checked_add(&1u))
293+
}
294+
}
266295
}
267296

268297
// Appending
@@ -453,6 +482,7 @@ pub struct WindowIter<'self, T> {
453482
}
454483

455484
impl<'self, T> Iterator<&'self [T]> for WindowIter<'self, T> {
485+
#[inline]
456486
fn next(&mut self) -> Option<&'self [T]> {
457487
if self.size > self.v.len() {
458488
None
@@ -462,6 +492,16 @@ impl<'self, T> Iterator<&'self [T]> for WindowIter<'self, T> {
462492
ret
463493
}
464494
}
495+
496+
#[inline]
497+
fn size_hint(&self) -> (uint, Option<uint>) {
498+
if self.size > self.v.len() {
499+
(0, Some(0))
500+
} else {
501+
let x = self.v.len() - self.size;
502+
(x.saturating_add(1), x.checked_add(&1u))
503+
}
504+
}
465505
}
466506

467507
/// An iterator over a vector in (non-overlapping) chunks (`size`
@@ -476,6 +516,7 @@ pub struct ChunkIter<'self, T> {
476516
}
477517

478518
impl<'self, T> Iterator<&'self [T]> for ChunkIter<'self, T> {
519+
#[inline]
479520
fn next(&mut self) -> Option<&'self [T]> {
480521
if self.v.len() == 0 {
481522
None
@@ -487,9 +528,21 @@ impl<'self, T> Iterator<&'self [T]> for ChunkIter<'self, T> {
487528
Some(fst)
488529
}
489530
}
531+
532+
#[inline]
533+
fn size_hint(&self) -> (uint, Option<uint>) {
534+
if self.v.len() == 0 {
535+
(0, Some(0))
536+
} else {
537+
let (n, rem) = self.v.len().div_rem(&self.size);
538+
let n = if rem > 0 { n+1 } else { n };
539+
(n, Some(n))
540+
}
541+
}
490542
}
491543

492544
impl<'self, T> DoubleEndedIterator<&'self [T]> for ChunkIter<'self, T> {
545+
#[inline]
493546
fn next_back(&mut self) -> Option<&'self [T]> {
494547
if self.v.len() == 0 {
495548
None
@@ -2236,6 +2289,7 @@ impl<'self, T> RandomAccessIterator<&'self T> for VecIterator<'self, T> {
22362289
exact
22372290
}
22382291

2292+
#[inline]
22392293
fn idx(&self, index: uint) -> Option<&'self T> {
22402294
unsafe {
22412295
if index < self.indexable() {
@@ -2281,6 +2335,7 @@ pub struct MoveIterator<T> {
22812335
}
22822336

22832337
impl<T> Iterator<T> for MoveIterator<T> {
2338+
#[inline]
22842339
fn next(&mut self) -> Option<T> {
22852340
// this is peculiar, but is required for safety with respect
22862341
// to dtors. It traverses the first half of the vec, and
@@ -2298,6 +2353,12 @@ impl<T> Iterator<T> for MoveIterator<T> {
22982353

22992354
self.v.pop_opt()
23002355
}
2356+
2357+
#[inline]
2358+
fn size_hint(&self) -> (uint, Option<uint>) {
2359+
let l = self.v.len();
2360+
(l, Some(l))
2361+
}
23012362
}
23022363

23032364
/// An iterator that moves out of a vector in reverse order.
@@ -2307,9 +2368,16 @@ pub struct MoveRevIterator<T> {
23072368
}
23082369

23092370
impl<T> Iterator<T> for MoveRevIterator<T> {
2371+
#[inline]
23102372
fn next(&mut self) -> Option<T> {
23112373
self.v.pop_opt()
23122374
}
2375+
2376+
#[inline]
2377+
fn size_hint(&self) -> (uint, Option<uint>) {
2378+
let l = self.v.len();
2379+
(l, Some(l))
2380+
}
23132381
}
23142382

23152383
impl<A> FromIterator<A> for ~[A] {

0 commit comments

Comments
 (0)