Skip to content

Commit e94e4d5

Browse files
committed
auto merge of #8120 : blake2-ppc/rust/iterator-fixes, r=thestinger
Implement RandomAccessIterator (RAI) where possible, for Iterator adaptors such as Map, Enumerate, Peek, Skip, Take, Cycle, where the adapted iterator is already RAI, and for collections where it is relevant (ringbuf and bitv). After discussion with thestinger, remove the RAI impl for VecMutIterator, we cannot soundly provide mutable access with this trait. Implement Extendable everywhere FromIterator is already implemented. Fixes issue #8108.
2 parents bb996bf + 99490ad commit e94e4d5

File tree

10 files changed

+471
-102
lines changed

10 files changed

+471
-102
lines changed

src/libextra/bitv.rs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212

1313

1414
use std::cmp;
15+
use std::iterator::{DoubleEndedIterator, RandomAccessIterator, Invert};
1516
use std::num;
1617
use std::ops;
1718
use std::uint;
1819
use std::vec;
1920

21+
2022
#[deriving(Clone)]
2123
struct SmallBitv {
2224
/// only the lowest nbits of this value are used. the rest is undefined.
@@ -404,7 +406,12 @@ impl Bitv {
404406

405407
#[inline]
406408
pub fn iter<'a>(&'a self) -> BitvIterator<'a> {
407-
BitvIterator {bitv: self, next_idx: 0}
409+
BitvIterator {bitv: self, next_idx: 0, end_idx: self.nbits}
410+
}
411+
412+
#[inline]
413+
pub fn rev_liter<'a>(&'a self) -> Invert<BitvIterator<'a>> {
414+
self.iter().invert()
408415
}
409416

410417
/// Returns true if all bits are 0
@@ -564,13 +571,14 @@ fn iterate_bits(base: uint, bits: uint, f: &fn(uint) -> bool) -> bool {
564571
/// An iterator for Bitv
565572
pub struct BitvIterator<'self> {
566573
priv bitv: &'self Bitv,
567-
priv next_idx: uint
574+
priv next_idx: uint,
575+
priv end_idx: uint,
568576
}
569577

570578
impl<'self> Iterator<bool> for BitvIterator<'self> {
571579
#[inline]
572580
fn next(&mut self) -> Option<bool> {
573-
if self.next_idx < self.bitv.nbits {
581+
if self.next_idx != self.end_idx {
574582
let idx = self.next_idx;
575583
self.next_idx += 1;
576584
Some(self.bitv.get(idx))
@@ -580,11 +588,39 @@ impl<'self> Iterator<bool> for BitvIterator<'self> {
580588
}
581589

582590
fn size_hint(&self) -> (uint, Option<uint>) {
583-
let rem = self.bitv.nbits - self.next_idx;
591+
let rem = self.end_idx - self.next_idx;
584592
(rem, Some(rem))
585593
}
586594
}
587595

596+
impl<'self> DoubleEndedIterator<bool> for BitvIterator<'self> {
597+
#[inline]
598+
fn next_back(&mut self) -> Option<bool> {
599+
if self.next_idx != self.end_idx {
600+
self.end_idx -= 1;
601+
Some(self.bitv.get(self.end_idx))
602+
} else {
603+
None
604+
}
605+
}
606+
}
607+
608+
impl<'self> RandomAccessIterator<bool> for BitvIterator<'self> {
609+
#[inline]
610+
fn indexable(&self) -> uint {
611+
self.end_idx - self.next_idx
612+
}
613+
614+
#[inline]
615+
fn idx(&self, index: uint) -> Option<bool> {
616+
if index >= self.indexable() {
617+
None
618+
} else {
619+
Some(self.bitv.get(index))
620+
}
621+
}
622+
}
623+
588624
/// An implementation of a set using a bit vector as an underlying
589625
/// representation for holding numerical elements.
590626
///

src/libextra/dlist.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
use std::cast;
2626
use std::ptr;
2727
use std::util;
28-
use std::iterator::{FromIterator, Invert};
28+
use std::iterator::{FromIterator, Extendable, Invert};
2929

3030
use container::Deque;
3131

@@ -541,11 +541,17 @@ impl<A> DoubleEndedIterator<A> for ConsumeIterator<A> {
541541
impl<A, T: Iterator<A>> FromIterator<A, T> for DList<A> {
542542
fn from_iterator(iterator: &mut T) -> DList<A> {
543543
let mut ret = DList::new();
544-
for iterator.advance |elt| { ret.push_back(elt); }
544+
ret.extend(iterator);
545545
ret
546546
}
547547
}
548548

549+
impl<A, T: Iterator<A>> Extendable<A, T> for DList<A> {
550+
fn extend(&mut self, iterator: &mut T) {
551+
for iterator.advance |elt| { self.push_back(elt); }
552+
}
553+
}
554+
549555
impl<A: Eq> Eq for DList<A> {
550556
fn eq(&self, other: &DList<A>) -> bool {
551557
self.len() == other.len() &&

src/libextra/priority_queue.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::clone::Clone;
1616
use std::unstable::intrinsics::{move_val_init, init};
1717
use std::util::{replace, swap};
1818
use std::vec;
19-
use std::iterator::FromIterator;
19+
use std::iterator::{FromIterator, Extendable};
2020

2121
/// A priority queue implemented with a binary heap
2222
#[deriving(Clone)]
@@ -191,17 +191,24 @@ impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
191191
}
192192

193193
impl<T: Ord, Iter: Iterator<T>> FromIterator<T, Iter> for PriorityQueue<T> {
194-
pub fn from_iterator(iter: &mut Iter) -> PriorityQueue<T> {
194+
fn from_iterator(iter: &mut Iter) -> PriorityQueue<T> {
195+
let mut q = PriorityQueue::new();
196+
q.extend(iter);
197+
198+
q
199+
}
200+
}
201+
202+
impl<T: Ord, Iter: Iterator<T>> Extendable<T, Iter> for PriorityQueue<T> {
203+
fn extend(&mut self, iter: &mut Iter) {
195204
let (lower, _) = iter.size_hint();
196205

197-
let mut q = PriorityQueue::new();
198-
q.reserve_at_least(lower);
206+
let len = self.capacity();
207+
self.reserve_at_least(len + lower);
199208

200209
for iter.advance |elem| {
201-
q.push(elem);
210+
self.push(elem);
202211
}
203-
204-
q
205212
}
206213
}
207214

src/libextra/ringbuf.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use std::num;
1717
use std::uint;
1818
use std::vec;
19-
use std::iterator::{FromIterator, Invert};
19+
use std::iterator::{FromIterator, Invert, RandomAccessIterator, Extendable};
2020

2121
use container::Deque;
2222

@@ -176,8 +176,7 @@ impl<T> RingBuf<T> {
176176

177177
/// Front-to-back iterator.
178178
pub fn iter<'a>(&'a self) -> RingBufIterator<'a, T> {
179-
RingBufIterator{index: 0, rindex: self.nelts - 1,
180-
nelts: self.nelts, elts: self.elts, lo: self.lo}
179+
RingBufIterator{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts}
181180
}
182181

183182
/// Back-to-front iterator.
@@ -187,8 +186,7 @@ impl<T> RingBuf<T> {
187186

188187
/// Front-to-back iterator which returns mutable values.
189188
pub fn mut_iter<'a>(&'a mut self) -> RingBufMutIterator<'a, T> {
190-
RingBufMutIterator{index: 0, rindex: self.nelts - 1,
191-
nelts: self.nelts, elts: self.elts, lo: self.lo}
189+
RingBufMutIterator{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts}
192190
}
193191

194192
/// Back-to-front iterator which returns mutable values.
@@ -202,18 +200,18 @@ macro_rules! iterator {
202200
impl<'self, T> Iterator<$elem> for $name<'self, T> {
203201
#[inline]
204202
fn next(&mut self) -> Option<$elem> {
205-
if self.nelts == 0 {
203+
if self.index == self.rindex {
206204
return None;
207205
}
208206
let raw_index = raw_index(self.lo, self.elts.len(), self.index);
209207
self.index += 1;
210-
self.nelts -= 1;
211-
Some(self.elts[raw_index]. $getter ())
208+
Some(self.elts[raw_index] . $getter ())
212209
}
213210

214211
#[inline]
215212
fn size_hint(&self) -> (uint, Option<uint>) {
216-
(self.nelts, Some(self.nelts))
213+
let len = self.rindex - self.index;
214+
(len, Some(len))
217215
}
218216
}
219217
}
@@ -224,33 +222,46 @@ macro_rules! iterator_rev {
224222
impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> {
225223
#[inline]
226224
fn next_back(&mut self) -> Option<$elem> {
227-
if self.nelts == 0 {
225+
if self.index == self.rindex {
228226
return None;
229227
}
230-
let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
231228
self.rindex -= 1;
232-
self.nelts -= 1;
233-
Some(self.elts[raw_index]. $getter ())
229+
let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
230+
Some(self.elts[raw_index] . $getter ())
234231
}
235232
}
236233
}
237234
}
238235

236+
239237
/// RingBuf iterator
240238
pub struct RingBufIterator<'self, T> {
241239
priv lo: uint,
242-
priv nelts: uint,
243240
priv index: uint,
244241
priv rindex: uint,
245242
priv elts: &'self [Option<T>],
246243
}
247244
iterator!{impl RingBufIterator -> &'self T, get_ref}
248245
iterator_rev!{impl RingBufIterator -> &'self T, get_ref}
249246

247+
impl<'self, T> RandomAccessIterator<&'self T> for RingBufIterator<'self, T> {
248+
#[inline]
249+
fn indexable(&self) -> uint { self.rindex - self.index }
250+
251+
#[inline]
252+
fn idx(&self, j: uint) -> Option<&'self T> {
253+
if j >= self.indexable() {
254+
None
255+
} else {
256+
let raw_index = raw_index(self.lo, self.elts.len(), self.index + j);
257+
Some(self.elts[raw_index].get_ref())
258+
}
259+
}
260+
}
261+
250262
/// RingBuf mutable iterator
251263
pub struct RingBufMutIterator<'self, T> {
252264
priv lo: uint,
253-
priv nelts: uint,
254265
priv index: uint,
255266
priv rindex: uint,
256267
priv elts: &'self mut [Option<T>],
@@ -314,11 +325,18 @@ impl<A: Eq> Eq for RingBuf<A> {
314325

315326
impl<A, T: Iterator<A>> FromIterator<A, T> for RingBuf<A> {
316327
fn from_iterator(iterator: &mut T) -> RingBuf<A> {
317-
let mut deq = RingBuf::new();
328+
let (lower, _) = iterator.size_hint();
329+
let mut deq = RingBuf::with_capacity(lower);
330+
deq.extend(iterator);
331+
deq
332+
}
333+
}
334+
335+
impl<A, T: Iterator<A>> Extendable<A, T> for RingBuf<A> {
336+
fn extend(&mut self, iterator: &mut T) {
318337
for iterator.advance |elt| {
319-
deq.push_back(elt);
338+
self.push_back(elt);
320339
}
321-
deq
322340
}
323341
}
324342

src/libextra/treemap.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
use std::num;
1717
use std::util::{swap, replace};
18-
use std::iterator::FromIterator;
18+
use std::iterator::{FromIterator, Extendable};
1919

2020
// This is implemented as an AA tree, which is a simplified variation of
2121
// a red-black tree where red (horizontal) nodes can only be added
@@ -753,26 +753,36 @@ fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
753753
}
754754

755755
impl<K: TotalOrd, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for TreeMap<K, V> {
756-
pub fn from_iterator(iter: &mut T) -> TreeMap<K, V> {
756+
fn from_iterator(iter: &mut T) -> TreeMap<K, V> {
757757
let mut map = TreeMap::new();
758+
map.extend(iter);
759+
map
760+
}
761+
}
758762

763+
impl<K: TotalOrd, V, T: Iterator<(K, V)>> Extendable<(K, V), T> for TreeMap<K, V> {
764+
#[inline]
765+
fn extend(&mut self, iter: &mut T) {
759766
for iter.advance |(k, v)| {
760-
map.insert(k, v);
767+
self.insert(k, v);
761768
}
762-
763-
map
764769
}
765770
}
766771

767772
impl<T: TotalOrd, Iter: Iterator<T>> FromIterator<T, Iter> for TreeSet<T> {
768773
pub fn from_iterator(iter: &mut Iter) -> TreeSet<T> {
769774
let mut set = TreeSet::new();
775+
set.extend(iter);
776+
set
777+
}
778+
}
770779

780+
impl<T: TotalOrd, Iter: Iterator<T>> Extendable<T, Iter> for TreeSet<T> {
781+
#[inline]
782+
fn extend(&mut self, iter: &mut Iter) {
771783
for iter.advance |elem| {
772-
set.insert(elem);
784+
self.insert(elem);
773785
}
774-
775-
set
776786
}
777787
}
778788

src/libstd/hashmap.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
1919
use clone::Clone;
2020
use cmp::{Eq, Equiv};
2121
use hash::Hash;
22-
use iterator::{Iterator, IteratorUtil, FromIterator, Chain};
22+
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, Chain};
2323
use num;
2424
use option::{None, Option, Some};
2525
use rand::RngUtil;
@@ -618,15 +618,19 @@ impl<K> Iterator<K> for HashSetConsumeIterator<K> {
618618
}
619619

620620
impl<K: Eq + Hash, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for HashMap<K, V> {
621-
pub fn from_iterator(iter: &mut T) -> HashMap<K, V> {
621+
fn from_iterator(iter: &mut T) -> HashMap<K, V> {
622622
let (lower, _) = iter.size_hint();
623623
let mut map = HashMap::with_capacity(lower);
624+
map.extend(iter);
625+
map
626+
}
627+
}
624628

629+
impl<K: Eq + Hash, V, T: Iterator<(K, V)>> Extendable<(K, V), T> for HashMap<K, V> {
630+
fn extend(&mut self, iter: &mut T) {
625631
for iter.advance |(k, v)| {
626-
map.insert(k, v);
632+
self.insert(k, v);
627633
}
628-
629-
map
630634
}
631635
}
632636

@@ -771,15 +775,19 @@ impl<T:Hash + Eq> HashSet<T> {
771775
}
772776

773777
impl<K: Eq + Hash, T: Iterator<K>> FromIterator<K, T> for HashSet<K> {
774-
pub fn from_iterator(iter: &mut T) -> HashSet<K> {
778+
fn from_iterator(iter: &mut T) -> HashSet<K> {
775779
let (lower, _) = iter.size_hint();
776780
let mut set = HashSet::with_capacity(lower);
781+
set.extend(iter);
782+
set
783+
}
784+
}
777785

786+
impl<K: Eq + Hash, T: Iterator<K>> Extendable<K, T> for HashSet<K> {
787+
fn extend(&mut self, iter: &mut T) {
778788
for iter.advance |k| {
779-
set.insert(k);
789+
self.insert(k);
780790
}
781-
782-
set
783791
}
784792
}
785793

0 commit comments

Comments
 (0)