1
Fork 0

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.
This commit is contained in:
bors 2013-07-29 19:04:22 -07:00
commit e94e4d51ca
10 changed files with 487 additions and 118 deletions

View file

@ -12,11 +12,13 @@
use std::cmp; use std::cmp;
use std::iterator::{DoubleEndedIterator, RandomAccessIterator, Invert};
use std::num; use std::num;
use std::ops; use std::ops;
use std::uint; use std::uint;
use std::vec; use std::vec;
#[deriving(Clone)] #[deriving(Clone)]
struct SmallBitv { struct SmallBitv {
/// only the lowest nbits of this value are used. the rest is undefined. /// only the lowest nbits of this value are used. the rest is undefined.
@ -404,7 +406,12 @@ impl Bitv {
#[inline] #[inline]
pub fn iter<'a>(&'a self) -> BitvIterator<'a> { pub fn iter<'a>(&'a self) -> BitvIterator<'a> {
BitvIterator {bitv: self, next_idx: 0} BitvIterator {bitv: self, next_idx: 0, end_idx: self.nbits}
}
#[inline]
pub fn rev_liter<'a>(&'a self) -> Invert<BitvIterator<'a>> {
self.iter().invert()
} }
/// Returns true if all bits are 0 /// Returns true if all bits are 0
@ -564,13 +571,14 @@ fn iterate_bits(base: uint, bits: uint, f: &fn(uint) -> bool) -> bool {
/// An iterator for Bitv /// An iterator for Bitv
pub struct BitvIterator<'self> { pub struct BitvIterator<'self> {
priv bitv: &'self Bitv, priv bitv: &'self Bitv,
priv next_idx: uint priv next_idx: uint,
priv end_idx: uint,
} }
impl<'self> Iterator<bool> for BitvIterator<'self> { impl<'self> Iterator<bool> for BitvIterator<'self> {
#[inline] #[inline]
fn next(&mut self) -> Option<bool> { fn next(&mut self) -> Option<bool> {
if self.next_idx < self.bitv.nbits { if self.next_idx != self.end_idx {
let idx = self.next_idx; let idx = self.next_idx;
self.next_idx += 1; self.next_idx += 1;
Some(self.bitv.get(idx)) Some(self.bitv.get(idx))
@ -580,11 +588,39 @@ impl<'self> Iterator<bool> for BitvIterator<'self> {
} }
fn size_hint(&self) -> (uint, Option<uint>) { fn size_hint(&self) -> (uint, Option<uint>) {
let rem = self.bitv.nbits - self.next_idx; let rem = self.end_idx - self.next_idx;
(rem, Some(rem)) (rem, Some(rem))
} }
} }
impl<'self> DoubleEndedIterator<bool> for BitvIterator<'self> {
#[inline]
fn next_back(&mut self) -> Option<bool> {
if self.next_idx != self.end_idx {
self.end_idx -= 1;
Some(self.bitv.get(self.end_idx))
} else {
None
}
}
}
impl<'self> RandomAccessIterator<bool> for BitvIterator<'self> {
#[inline]
fn indexable(&self) -> uint {
self.end_idx - self.next_idx
}
#[inline]
fn idx(&self, index: uint) -> Option<bool> {
if index >= self.indexable() {
None
} else {
Some(self.bitv.get(index))
}
}
}
/// An implementation of a set using a bit vector as an underlying /// An implementation of a set using a bit vector as an underlying
/// representation for holding numerical elements. /// representation for holding numerical elements.
/// ///

View file

@ -25,7 +25,7 @@
use std::cast; use std::cast;
use std::ptr; use std::ptr;
use std::util; use std::util;
use std::iterator::{FromIterator, Invert}; use std::iterator::{FromIterator, Extendable, Invert};
use container::Deque; use container::Deque;
@ -541,11 +541,17 @@ impl<A> DoubleEndedIterator<A> for ConsumeIterator<A> {
impl<A, T: Iterator<A>> FromIterator<A, T> for DList<A> { impl<A, T: Iterator<A>> FromIterator<A, T> for DList<A> {
fn from_iterator(iterator: &mut T) -> DList<A> { fn from_iterator(iterator: &mut T) -> DList<A> {
let mut ret = DList::new(); let mut ret = DList::new();
for iterator.advance |elt| { ret.push_back(elt); } ret.extend(iterator);
ret ret
} }
} }
impl<A, T: Iterator<A>> Extendable<A, T> for DList<A> {
fn extend(&mut self, iterator: &mut T) {
for iterator.advance |elt| { self.push_back(elt); }
}
}
impl<A: Eq> Eq for DList<A> { impl<A: Eq> Eq for DList<A> {
fn eq(&self, other: &DList<A>) -> bool { fn eq(&self, other: &DList<A>) -> bool {
self.len() == other.len() && self.len() == other.len() &&

View file

@ -16,7 +16,7 @@ use std::clone::Clone;
use std::unstable::intrinsics::{move_val_init, init}; use std::unstable::intrinsics::{move_val_init, init};
use std::util::{replace, swap}; use std::util::{replace, swap};
use std::vec; use std::vec;
use std::iterator::FromIterator; use std::iterator::{FromIterator, Extendable};
/// A priority queue implemented with a binary heap /// A priority queue implemented with a binary heap
#[deriving(Clone)] #[deriving(Clone)]
@ -191,20 +191,27 @@ impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> {
} }
impl<T: Ord, Iter: Iterator<T>> FromIterator<T, Iter> for PriorityQueue<T> { impl<T: Ord, Iter: Iterator<T>> FromIterator<T, Iter> for PriorityQueue<T> {
pub fn from_iterator(iter: &mut Iter) -> PriorityQueue<T> { fn from_iterator(iter: &mut Iter) -> PriorityQueue<T> {
let (lower, _) = iter.size_hint();
let mut q = PriorityQueue::new(); let mut q = PriorityQueue::new();
q.reserve_at_least(lower); q.extend(iter);
for iter.advance |elem| {
q.push(elem);
}
q q
} }
} }
impl<T: Ord, Iter: Iterator<T>> Extendable<T, Iter> for PriorityQueue<T> {
fn extend(&mut self, iter: &mut Iter) {
let (lower, _) = iter.size_hint();
let len = self.capacity();
self.reserve_at_least(len + lower);
for iter.advance |elem| {
self.push(elem);
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use sort::merge_sort; use sort::merge_sort;

View file

@ -16,7 +16,7 @@
use std::num; use std::num;
use std::uint; use std::uint;
use std::vec; use std::vec;
use std::iterator::{FromIterator, Invert}; use std::iterator::{FromIterator, Invert, RandomAccessIterator, Extendable};
use container::Deque; use container::Deque;
@ -176,8 +176,7 @@ impl<T> RingBuf<T> {
/// Front-to-back iterator. /// Front-to-back iterator.
pub fn iter<'a>(&'a self) -> RingBufIterator<'a, T> { pub fn iter<'a>(&'a self) -> RingBufIterator<'a, T> {
RingBufIterator{index: 0, rindex: self.nelts - 1, RingBufIterator{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts}
nelts: self.nelts, elts: self.elts, lo: self.lo}
} }
/// Back-to-front iterator. /// Back-to-front iterator.
@ -187,8 +186,7 @@ impl<T> RingBuf<T> {
/// Front-to-back iterator which returns mutable values. /// Front-to-back iterator which returns mutable values.
pub fn mut_iter<'a>(&'a mut self) -> RingBufMutIterator<'a, T> { pub fn mut_iter<'a>(&'a mut self) -> RingBufMutIterator<'a, T> {
RingBufMutIterator{index: 0, rindex: self.nelts - 1, RingBufMutIterator{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts}
nelts: self.nelts, elts: self.elts, lo: self.lo}
} }
/// Back-to-front iterator which returns mutable values. /// Back-to-front iterator which returns mutable values.
@ -202,18 +200,18 @@ macro_rules! iterator {
impl<'self, T> Iterator<$elem> for $name<'self, T> { impl<'self, T> Iterator<$elem> for $name<'self, T> {
#[inline] #[inline]
fn next(&mut self) -> Option<$elem> { fn next(&mut self) -> Option<$elem> {
if self.nelts == 0 { if self.index == self.rindex {
return None; return None;
} }
let raw_index = raw_index(self.lo, self.elts.len(), self.index); let raw_index = raw_index(self.lo, self.elts.len(), self.index);
self.index += 1; self.index += 1;
self.nelts -= 1; Some(self.elts[raw_index] . $getter ())
Some(self.elts[raw_index]. $getter ())
} }
#[inline] #[inline]
fn size_hint(&self) -> (uint, Option<uint>) { fn size_hint(&self) -> (uint, Option<uint>) {
(self.nelts, Some(self.nelts)) let len = self.rindex - self.index;
(len, Some(len))
} }
} }
} }
@ -224,22 +222,21 @@ macro_rules! iterator_rev {
impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> { impl<'self, T> DoubleEndedIterator<$elem> for $name<'self, T> {
#[inline] #[inline]
fn next_back(&mut self) -> Option<$elem> { fn next_back(&mut self) -> Option<$elem> {
if self.nelts == 0 { if self.index == self.rindex {
return None; return None;
} }
let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
self.rindex -= 1; self.rindex -= 1;
self.nelts -= 1; let raw_index = raw_index(self.lo, self.elts.len(), self.rindex);
Some(self.elts[raw_index]. $getter ()) Some(self.elts[raw_index] . $getter ())
} }
} }
} }
} }
/// RingBuf iterator /// RingBuf iterator
pub struct RingBufIterator<'self, T> { pub struct RingBufIterator<'self, T> {
priv lo: uint, priv lo: uint,
priv nelts: uint,
priv index: uint, priv index: uint,
priv rindex: uint, priv rindex: uint,
priv elts: &'self [Option<T>], priv elts: &'self [Option<T>],
@ -247,10 +244,24 @@ pub struct RingBufIterator<'self, T> {
iterator!{impl RingBufIterator -> &'self T, get_ref} iterator!{impl RingBufIterator -> &'self T, get_ref}
iterator_rev!{impl RingBufIterator -> &'self T, get_ref} iterator_rev!{impl RingBufIterator -> &'self T, get_ref}
impl<'self, T> RandomAccessIterator<&'self T> for RingBufIterator<'self, T> {
#[inline]
fn indexable(&self) -> uint { self.rindex - self.index }
#[inline]
fn idx(&self, j: uint) -> Option<&'self T> {
if j >= self.indexable() {
None
} else {
let raw_index = raw_index(self.lo, self.elts.len(), self.index + j);
Some(self.elts[raw_index].get_ref())
}
}
}
/// RingBuf mutable iterator /// RingBuf mutable iterator
pub struct RingBufMutIterator<'self, T> { pub struct RingBufMutIterator<'self, T> {
priv lo: uint, priv lo: uint,
priv nelts: uint,
priv index: uint, priv index: uint,
priv rindex: uint, priv rindex: uint,
priv elts: &'self mut [Option<T>], priv elts: &'self mut [Option<T>],
@ -314,14 +325,21 @@ impl<A: Eq> Eq for RingBuf<A> {
impl<A, T: Iterator<A>> FromIterator<A, T> for RingBuf<A> { impl<A, T: Iterator<A>> FromIterator<A, T> for RingBuf<A> {
fn from_iterator(iterator: &mut T) -> RingBuf<A> { fn from_iterator(iterator: &mut T) -> RingBuf<A> {
let mut deq = RingBuf::new(); let (lower, _) = iterator.size_hint();
for iterator.advance |elt| { let mut deq = RingBuf::with_capacity(lower);
deq.push_back(elt); deq.extend(iterator);
}
deq deq
} }
} }
impl<A, T: Iterator<A>> Extendable<A, T> for RingBuf<A> {
fn extend(&mut self, iterator: &mut T) {
for iterator.advance |elt| {
self.push_back(elt);
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -15,7 +15,7 @@
use std::num; use std::num;
use std::util::{swap, replace}; use std::util::{swap, replace};
use std::iterator::FromIterator; use std::iterator::{FromIterator, Extendable};
// This is implemented as an AA tree, which is a simplified variation of // This is implemented as an AA tree, which is a simplified variation of
// a red-black tree where red (horizontal) nodes can only be added // a red-black tree where red (horizontal) nodes can only be added
@ -753,29 +753,39 @@ fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
} }
impl<K: TotalOrd, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for TreeMap<K, V> { impl<K: TotalOrd, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for TreeMap<K, V> {
pub fn from_iterator(iter: &mut T) -> TreeMap<K, V> { fn from_iterator(iter: &mut T) -> TreeMap<K, V> {
let mut map = TreeMap::new(); let mut map = TreeMap::new();
map.extend(iter);
for iter.advance |(k, v)| {
map.insert(k, v);
}
map map
} }
} }
impl<K: TotalOrd, V, T: Iterator<(K, V)>> Extendable<(K, V), T> for TreeMap<K, V> {
#[inline]
fn extend(&mut self, iter: &mut T) {
for iter.advance |(k, v)| {
self.insert(k, v);
}
}
}
impl<T: TotalOrd, Iter: Iterator<T>> FromIterator<T, Iter> for TreeSet<T> { impl<T: TotalOrd, Iter: Iterator<T>> FromIterator<T, Iter> for TreeSet<T> {
pub fn from_iterator(iter: &mut Iter) -> TreeSet<T> { pub fn from_iterator(iter: &mut Iter) -> TreeSet<T> {
let mut set = TreeSet::new(); let mut set = TreeSet::new();
set.extend(iter);
for iter.advance |elem| {
set.insert(elem);
}
set set
} }
} }
impl<T: TotalOrd, Iter: Iterator<T>> Extendable<T, Iter> for TreeSet<T> {
#[inline]
fn extend(&mut self, iter: &mut Iter) {
for iter.advance |elem| {
self.insert(elem);
}
}
}
#[cfg(test)] #[cfg(test)]
mod test_treemap { mod test_treemap {

View file

@ -19,7 +19,7 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
use clone::Clone; use clone::Clone;
use cmp::{Eq, Equiv}; use cmp::{Eq, Equiv};
use hash::Hash; use hash::Hash;
use iterator::{Iterator, IteratorUtil, FromIterator, Chain}; use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, Chain};
use num; use num;
use option::{None, Option, Some}; use option::{None, Option, Some};
use rand::RngUtil; use rand::RngUtil;
@ -618,18 +618,22 @@ impl<K> Iterator<K> for HashSetConsumeIterator<K> {
} }
impl<K: Eq + Hash, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for HashMap<K, V> { impl<K: Eq + Hash, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for HashMap<K, V> {
pub fn from_iterator(iter: &mut T) -> HashMap<K, V> { fn from_iterator(iter: &mut T) -> HashMap<K, V> {
let (lower, _) = iter.size_hint(); let (lower, _) = iter.size_hint();
let mut map = HashMap::with_capacity(lower); let mut map = HashMap::with_capacity(lower);
map.extend(iter);
for iter.advance |(k, v)| {
map.insert(k, v);
}
map map
} }
} }
impl<K: Eq + Hash, V, T: Iterator<(K, V)>> Extendable<(K, V), T> for HashMap<K, V> {
fn extend(&mut self, iter: &mut T) {
for iter.advance |(k, v)| {
self.insert(k, v);
}
}
}
/// An implementation of a hash set using the underlying representation of a /// An implementation of a hash set using the underlying representation of a
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet` /// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// requires that the elements implement the `Eq` and `Hash` traits. /// requires that the elements implement the `Eq` and `Hash` traits.
@ -771,18 +775,22 @@ impl<T:Hash + Eq> HashSet<T> {
} }
impl<K: Eq + Hash, T: Iterator<K>> FromIterator<K, T> for HashSet<K> { impl<K: Eq + Hash, T: Iterator<K>> FromIterator<K, T> for HashSet<K> {
pub fn from_iterator(iter: &mut T) -> HashSet<K> { fn from_iterator(iter: &mut T) -> HashSet<K> {
let (lower, _) = iter.size_hint(); let (lower, _) = iter.size_hint();
let mut set = HashSet::with_capacity(lower); let mut set = HashSet::with_capacity(lower);
set.extend(iter);
for iter.advance |k| {
set.insert(k);
}
set set
} }
} }
impl<K: Eq + Hash, T: Iterator<K>> Extendable<K, T> for HashSet<K> {
fn extend(&mut self, iter: &mut T) {
for iter.advance |k| {
self.insert(k);
}
}
}
// FIXME #7814: use std::iterator::FilterIterator // FIXME #7814: use std::iterator::FilterIterator
/// Building block for Set operation iterators /// Building block for Set operation iterators
pub struct EnvFilterIterator<A, Env, I> { pub struct EnvFilterIterator<A, Env, I> {

View file

@ -529,7 +529,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
#[inline] #[inline]
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U) fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> U)
-> FlatMap<'r, A, T, U> { -> FlatMap<'r, A, T, U> {
FlatMap{iter: self, f: f, subiter: None } FlatMap{iter: self, f: f, frontiter: None, backiter: None }
} }
// FIXME: #5898: should be called `peek` // FIXME: #5898: should be called `peek`
@ -811,6 +811,30 @@ impl<A, T: Clone + Iterator<A>> Iterator<A> for Cycle<T> {
} }
} }
impl<A, T: Clone + RandomAccessIterator<A>> RandomAccessIterator<A> for Cycle<T> {
#[inline]
fn indexable(&self) -> uint {
if self.orig.indexable() > 0 {
uint::max_value
} else {
0
}
}
#[inline]
fn idx(&self, index: uint) -> Option<A> {
let liter = self.iter.indexable();
let lorig = self.orig.indexable();
if lorig == 0 {
None
} else if index < liter {
self.iter.idx(index)
} else {
self.orig.idx((index - liter) % lorig)
}
}
}
/// An iterator which strings two iterators together /// An iterator which strings two iterators together
#[deriving(Clone)] #[deriving(Clone)]
pub struct Chain<T, U> { pub struct Chain<T, U> {
@ -924,20 +948,44 @@ impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for Zip<T, U> {
} }
} }
impl<A, B, T: RandomAccessIterator<A>, U: RandomAccessIterator<B>>
RandomAccessIterator<(A, B)> for Zip<T, U> {
#[inline]
fn indexable(&self) -> uint {
cmp::min(self.a.indexable(), self.b.indexable())
}
#[inline]
fn idx(&self, index: uint) -> Option<(A, B)> {
match (self.a.idx(index), self.b.idx(index)) {
(Some(x), Some(y)) => Some((x, y)),
_ => None
}
}
}
/// An iterator which maps the values of `iter` with `f` /// An iterator which maps the values of `iter` with `f`
pub struct Map<'self, A, B, T> { pub struct Map<'self, A, B, T> {
priv iter: T, priv iter: T,
priv f: &'self fn(A) -> B priv f: &'self fn(A) -> B
} }
impl<'self, A, B, T: Iterator<A>> Iterator<B> for Map<'self, A, B, T> { impl<'self, A, B, T> Map<'self, A, B, T> {
#[inline] #[inline]
fn next(&mut self) -> Option<B> { fn do_map(&self, elt: Option<A>) -> Option<B> {
match self.iter.next() { match elt {
Some(a) => Some((self.f)(a)), Some(a) => Some((self.f)(a)),
_ => None _ => None
} }
} }
}
impl<'self, A, B, T: Iterator<A>> Iterator<B> for Map<'self, A, B, T> {
#[inline]
fn next(&mut self) -> Option<B> {
let next = self.iter.next();
self.do_map(next)
}
#[inline] #[inline]
fn size_hint(&self) -> (uint, Option<uint>) { fn size_hint(&self) -> (uint, Option<uint>) {
@ -949,10 +997,21 @@ impl<'self, A, B, T: DoubleEndedIterator<A>> DoubleEndedIterator<B>
for Map<'self, A, B, T> { for Map<'self, A, B, T> {
#[inline] #[inline]
fn next_back(&mut self) -> Option<B> { fn next_back(&mut self) -> Option<B> {
match self.iter.next_back() { let next = self.iter.next_back();
Some(a) => Some((self.f)(a)), self.do_map(next)
_ => None }
} }
impl<'self, A, B, T: RandomAccessIterator<A>> RandomAccessIterator<B>
for Map<'self, A, B, T> {
#[inline]
fn indexable(&self) -> uint {
self.iter.indexable()
}
#[inline]
fn idx(&self, index: uint) -> Option<B> {
self.do_map(self.iter.idx(index))
} }
} }
@ -1069,6 +1128,21 @@ impl<A, T: Iterator<A>> Iterator<(uint, A)> for Enumerate<T> {
} }
} }
impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<(uint, A)> for Enumerate<T> {
#[inline]
fn indexable(&self) -> uint {
self.iter.indexable()
}
#[inline]
fn idx(&self, index: uint) -> Option<(uint, A)> {
match self.iter.idx(index) {
Some(a) => Some((self.count + index, a)),
_ => None,
}
}
}
/// An iterator which rejects elements while `predicate` is true /// An iterator which rejects elements while `predicate` is true
pub struct SkipWhile<'self, A, T> { pub struct SkipWhile<'self, A, T> {
priv iter: T, priv iter: T,
@ -1189,6 +1263,27 @@ impl<A, T: Iterator<A>> Iterator<A> for Skip<T> {
} }
} }
impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Skip<T> {
#[inline]
fn indexable(&self) -> uint {
let N = self.iter.indexable();
if N < self.n {
0
} else {
N - self.n
}
}
#[inline]
fn idx(&self, index: uint) -> Option<A> {
if index >= self.indexable() {
None
} else {
self.iter.idx(index + self.n)
}
}
}
/// An iterator which only iterates over the first `n` iterations of `iter`. /// An iterator which only iterates over the first `n` iterations of `iter`.
#[deriving(Clone)] #[deriving(Clone)]
pub struct Take<T> { pub struct Take<T> {
@ -1223,6 +1318,23 @@ impl<A, T: Iterator<A>> Iterator<A> for Take<T> {
} }
} }
impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Take<T> {
#[inline]
fn indexable(&self) -> uint {
cmp::min(self.iter.indexable(), self.n)
}
#[inline]
fn idx(&self, index: uint) -> Option<A> {
if index >= self.n {
None
} else {
self.iter.idx(index)
}
}
}
/// An iterator to maintain state while iterating another iterator /// An iterator to maintain state while iterating another iterator
pub struct Scan<'self, A, B, T, St> { pub struct Scan<'self, A, B, T, St> {
priv iter: T, priv iter: T,
@ -1251,7 +1363,8 @@ impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for Scan<'self, A, B, T, St> {
pub struct FlatMap<'self, A, T, U> { pub struct FlatMap<'self, A, T, U> {
priv iter: T, priv iter: T,
priv f: &'self fn(A) -> U, priv f: &'self fn(A) -> U,
priv subiter: Option<U>, priv frontiter: Option<U>,
priv backiter: Option<U>,
} }
impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
@ -1259,14 +1372,45 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
#[inline] #[inline]
fn next(&mut self) -> Option<B> { fn next(&mut self) -> Option<B> {
loop { loop {
for self.subiter.mut_iter().advance |inner| { for self.frontiter.mut_iter().advance |inner| {
for inner.advance |x| { for inner.advance |x| {
return Some(x) return Some(x)
} }
} }
match self.iter.next().map_consume(|x| (self.f)(x)) { match self.iter.next().map_consume(|x| (self.f)(x)) {
None => return None, None => return self.backiter.chain_mut_ref(|it| it.next()),
next => self.subiter = next, next => self.frontiter = next,
}
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let (flo, fhi) = self.frontiter.map_default((0, Some(0)), |it| it.size_hint());
let (blo, bhi) = self.backiter.map_default((0, Some(0)), |it| it.size_hint());
match (self.iter.size_hint(), fhi, bhi) {
((0, Some(0)), Some(a), Some(b)) => (flo + blo, Some(a + b)),
_ => (flo + blo, None)
}
}
}
impl<'self,
A, T: DoubleEndedIterator<A>,
B, U: DoubleEndedIterator<B>> DoubleEndedIterator<B>
for FlatMap<'self, A, T, U> {
#[inline]
fn next_back(&mut self) -> Option<B> {
loop {
for self.backiter.mut_iter().advance |inner| {
match inner.next_back() {
None => (),
y => return y
}
}
match self.iter.next_back().map_consume(|x| (self.f)(x)) {
None => return self.frontiter.chain_mut_ref(|it| it.next_back()),
next => self.backiter = next,
} }
} }
} }
@ -1279,17 +1423,23 @@ pub struct Peek<'self, A, T> {
priv f: &'self fn(&A) priv f: &'self fn(&A)
} }
impl<'self, A, T: Iterator<A>> Iterator<A> for Peek<'self, A, T> { impl<'self, A, T> Peek<'self, A, T> {
#[inline] #[inline]
fn next(&mut self) -> Option<A> { fn do_peek(&self, elt: Option<A>) -> Option<A> {
let next = self.iter.next(); match elt {
match next {
Some(ref a) => (self.f)(a), Some(ref a) => (self.f)(a),
None => () None => ()
} }
next elt
}
}
impl<'self, A, T: Iterator<A>> Iterator<A> for Peek<'self, A, T> {
#[inline]
fn next(&mut self) -> Option<A> {
let next = self.iter.next();
self.do_peek(next)
} }
#[inline] #[inline]
@ -1302,13 +1452,19 @@ impl<'self, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Peek<'self,
#[inline] #[inline]
fn next_back(&mut self) -> Option<A> { fn next_back(&mut self) -> Option<A> {
let next = self.iter.next_back(); let next = self.iter.next_back();
self.do_peek(next)
}
}
match next { impl<'self, A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Peek<'self, A, T> {
Some(ref a) => (self.f)(a), #[inline]
None => () fn indexable(&self) -> uint {
} self.iter.indexable()
}
next #[inline]
fn idx(&self, index: uint) -> Option<A> {
self.do_peek(self.iter.idx(index))
} }
} }
@ -1376,6 +1532,7 @@ mod tests {
use super::*; use super::*;
use prelude::*; use prelude::*;
use cmp;
use uint; use uint;
#[test] #[test]
@ -1768,6 +1925,43 @@ mod tests {
assert_eq!(it.next_back(), None) assert_eq!(it.next_back(), None)
} }
#[cfg(test)]
fn check_randacc_iter<A: Eq, T: Clone + RandomAccessIterator<A>>(a: T, len: uint)
{
let mut b = a.clone();
assert_eq!(len, b.indexable());
let mut n = 0;
for a.enumerate().advance |(i, elt)| {
assert_eq!(Some(elt), b.idx(i));
n += 1;
}
assert_eq!(n, len);
assert_eq!(None, b.idx(n));
// call recursively to check after picking off an element
if len > 0 {
b.next();
check_randacc_iter(b, len-1);
}
}
#[test]
fn test_double_ended_flat_map() {
let u = [0u,1];
let v = [5,6,7,8];
let mut it = u.iter().flat_map_(|x| v.slice(*x, v.len()).iter());
assert_eq!(it.next_back().unwrap(), &8);
assert_eq!(it.next().unwrap(), &5);
assert_eq!(it.next_back().unwrap(), &7);
assert_eq!(it.next_back().unwrap(), &6);
assert_eq!(it.next_back().unwrap(), &8);
assert_eq!(it.next().unwrap(), &6);
assert_eq!(it.next_back().unwrap(), &7);
assert_eq!(it.next_back(), None);
assert_eq!(it.next(), None);
assert_eq!(it.next_back(), None);
}
#[test] #[test]
fn test_random_access_chain() { fn test_random_access_chain() {
let xs = [1, 2, 3, 4, 5]; let xs = [1, 2, 3, 4, 5];
@ -1785,5 +1979,71 @@ mod tests {
assert_eq!(it.idx(0).unwrap(), &3); assert_eq!(it.idx(0).unwrap(), &3);
assert_eq!(it.idx(4).unwrap(), &9); assert_eq!(it.idx(4).unwrap(), &9);
assert!(it.idx(6).is_none()); assert!(it.idx(6).is_none());
check_randacc_iter(it, xs.len() + ys.len() - 3);
}
#[test]
fn test_random_access_enumerate() {
let xs = [1, 2, 3, 4, 5];
check_randacc_iter(xs.iter().enumerate(), xs.len());
}
#[test]
fn test_random_access_zip() {
let xs = [1, 2, 3, 4, 5];
let ys = [7, 9, 11];
check_randacc_iter(xs.iter().zip(ys.iter()), cmp::min(xs.len(), ys.len()));
}
#[test]
fn test_random_access_take() {
let xs = [1, 2, 3, 4, 5];
let empty: &[int] = [];
check_randacc_iter(xs.iter().take_(3), 3);
check_randacc_iter(xs.iter().take_(20), xs.len());
check_randacc_iter(xs.iter().take_(0), 0);
check_randacc_iter(empty.iter().take_(2), 0);
}
#[test]
fn test_random_access_skip() {
let xs = [1, 2, 3, 4, 5];
let empty: &[int] = [];
check_randacc_iter(xs.iter().skip(2), xs.len() - 2);
check_randacc_iter(empty.iter().skip(2), 0);
}
#[test]
fn test_random_access_peek() {
let xs = [1, 2, 3, 4, 5];
// test .transform and .peek_ that don't implement Clone
let it = xs.iter().peek_(|_| {});
assert_eq!(xs.len(), it.indexable());
for xs.iter().enumerate().advance |(i, elt)| {
assert_eq!(Some(elt), it.idx(i));
}
}
#[test]
fn test_random_access_transform() {
let xs = [1, 2, 3, 4, 5];
// test .transform and .peek_ that don't implement Clone
let it = xs.iter().transform(|x| *x);
assert_eq!(xs.len(), it.indexable());
for xs.iter().enumerate().advance |(i, elt)| {
assert_eq!(Some(*elt), it.idx(i));
}
}
#[test]
fn test_random_access_cycle() {
let xs = [1, 2, 3, 4, 5];
let empty: &[int] = [];
check_randacc_iter(xs.iter().cycle().take_(27), 27);
check_randacc_iter(empty.iter().cycle(), 0);
} }
} }

View file

@ -23,7 +23,8 @@ use char::Char;
use clone::Clone; use clone::Clone;
use container::{Container, Mutable}; use container::{Container, Mutable};
use iter::Times; use iter::Times;
use iterator::{Iterator, FromIterator, IteratorUtil, Filter, AdditiveIterator, Map}; use iterator::{Iterator, FromIterator, Extendable, IteratorUtil};
use iterator::{Filter, AdditiveIterator, Map};
use libc; use libc;
use num::Zero; use num::Zero;
use option::{None, Option, Some}; use option::{None, Option, Some};
@ -2323,13 +2324,23 @@ impl<T: Iterator<char>> FromIterator<char, T> for ~str {
fn from_iterator(iterator: &mut T) -> ~str { fn from_iterator(iterator: &mut T) -> ~str {
let (lower, _) = iterator.size_hint(); let (lower, _) = iterator.size_hint();
let mut buf = with_capacity(lower); let mut buf = with_capacity(lower);
for iterator.advance |ch| { buf.extend(iterator);
buf.push_char(ch)
}
buf buf
} }
} }
impl<T: Iterator<char>> Extendable<char, T> for ~str {
#[inline]
fn extend(&mut self, iterator: &mut T) {
let (lower, _) = iterator.size_hint();
let reserve = lower + self.len();
self.reserve_at_least(reserve);
for iterator.advance |ch| {
self.push_char(ch)
}
}
}
// This works because every lifetime is a sub-lifetime of 'static // This works because every lifetime is a sub-lifetime of 'static
impl<'self> Zero for &'self str { impl<'self> Zero for &'self str {
fn zero() -> &'self str { "" } fn zero() -> &'self str { "" }
@ -2503,6 +2514,16 @@ mod tests {
assert_eq!(data, s.as_slice()); assert_eq!(data, s.as_slice());
} }
#[test]
fn test_extend() {
let data = ~"ประเทศไทย中";
let mut cpy = data.clone();
let other = "abc";
let mut it = other.iter();
cpy.extend(&mut it);
assert_eq!(cpy, data + other);
}
#[test] #[test]
fn test_clear() { fn test_clear() {
let mut empty = ~""; let mut empty = ~"";

View file

@ -11,7 +11,7 @@
//! An ordered map and set for integer keys implemented as a radix trie //! An ordered map and set for integer keys implemented as a radix trie
use prelude::*; use prelude::*;
use iterator::{IteratorUtil, FromIterator}; use iterator::{IteratorUtil, FromIterator, Extendable};
use uint; use uint;
use util::{swap, replace}; use util::{swap, replace};
@ -155,17 +155,21 @@ impl<T> TrieMap<T> {
} }
impl<T, Iter: Iterator<(uint, T)>> FromIterator<(uint, T), Iter> for TrieMap<T> { impl<T, Iter: Iterator<(uint, T)>> FromIterator<(uint, T), Iter> for TrieMap<T> {
pub fn from_iterator(iter: &mut Iter) -> TrieMap<T> { fn from_iterator(iter: &mut Iter) -> TrieMap<T> {
let mut map = TrieMap::new(); let mut map = TrieMap::new();
map.extend(iter);
for iter.advance |(k, v)| {
map.insert(k, v);
}
map map
} }
} }
impl<T, Iter: Iterator<(uint, T)>> Extendable<(uint, T), Iter> for TrieMap<T> {
fn extend(&mut self, iter: &mut Iter) {
for iter.advance |(k, v)| {
self.insert(k, v);
}
}
}
#[allow(missing_doc)] #[allow(missing_doc)]
pub struct TrieSet { pub struct TrieSet {
priv map: TrieMap<()> priv map: TrieMap<()>
@ -222,17 +226,21 @@ impl TrieSet {
} }
impl<Iter: Iterator<uint>> FromIterator<uint, Iter> for TrieSet { impl<Iter: Iterator<uint>> FromIterator<uint, Iter> for TrieSet {
pub fn from_iterator(iter: &mut Iter) -> TrieSet { fn from_iterator(iter: &mut Iter) -> TrieSet {
let mut set = TrieSet::new(); let mut set = TrieSet::new();
set.extend(iter);
for iter.advance |elem| {
set.insert(elem);
}
set set
} }
} }
impl<Iter: Iterator<uint>> Extendable<uint, Iter> for TrieSet {
fn extend(&mut self, iter: &mut Iter) {
for iter.advance |elem| {
self.insert(elem);
}
}
}
struct TrieNode<T> { struct TrieNode<T> {
count: uint, count: uint,
children: [Child<T>, ..SIZE] children: [Child<T>, ..SIZE]

View file

@ -2106,7 +2106,8 @@ macro_rules! iterator {
#[inline] #[inline]
fn size_hint(&self) -> (uint, Option<uint>) { fn size_hint(&self) -> (uint, Option<uint>) {
let exact = self.indexable(); let diff = (self.end as uint) - (self.ptr as uint);
let exact = diff / sys::nonzero_size_of::<T>();
(exact, Some(exact)) (exact, Some(exact))
} }
} }
@ -2134,23 +2135,19 @@ macro_rules! double_ended_iterator {
} }
} }
macro_rules! random_access_iterator { impl<'self, T> RandomAccessIterator<&'self T> for VecIterator<'self, T> {
(impl $name:ident -> $elem:ty) => { #[inline]
impl<'self, T> RandomAccessIterator<$elem> for $name<'self, T> { fn indexable(&self) -> uint {
#[inline] let (exact, _) = self.size_hint();
fn indexable(&self) -> uint { exact
let diff = (self.end as uint) - (self.ptr as uint); }
diff / sys::nonzero_size_of::<T>()
}
fn idx(&self, index: uint) -> Option<$elem> { fn idx(&self, index: uint) -> Option<&'self T> {
unsafe { unsafe {
if index < self.indexable() { if index < self.indexable() {
cast::transmute(self.ptr.offset(index)) cast::transmute(self.ptr.offset(index))
} else { } else {
None None
}
}
} }
} }
} }
@ -2165,7 +2162,6 @@ pub struct VecIterator<'self, T> {
} }
iterator!{impl VecIterator -> &'self T} iterator!{impl VecIterator -> &'self T}
double_ended_iterator!{impl VecIterator -> &'self T} double_ended_iterator!{impl VecIterator -> &'self T}
random_access_iterator!{impl VecIterator -> &'self T}
pub type RevIterator<'self, T> = Invert<VecIterator<'self, T>>; pub type RevIterator<'self, T> = Invert<VecIterator<'self, T>>;
impl<'self, T> Clone for VecIterator<'self, T> { impl<'self, T> Clone for VecIterator<'self, T> {
@ -2181,7 +2177,6 @@ pub struct VecMutIterator<'self, T> {
} }
iterator!{impl VecMutIterator -> &'self mut T} iterator!{impl VecMutIterator -> &'self mut T}
double_ended_iterator!{impl VecMutIterator -> &'self mut T} double_ended_iterator!{impl VecMutIterator -> &'self mut T}
random_access_iterator!{impl VecMutIterator -> &'self mut T}
pub type MutRevIterator<'self, T> = Invert<VecMutIterator<'self, T>>; pub type MutRevIterator<'self, T> = Invert<VecMutIterator<'self, T>>;
/// An iterator that moves out of a vector. /// An iterator that moves out of a vector.