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::iterator::{DoubleEndedIterator, RandomAccessIterator, Invert};
use std::num;
use std::ops;
use std::uint;
use std::vec;
#[deriving(Clone)]
struct SmallBitv {
/// only the lowest nbits of this value are used. the rest is undefined.
@ -404,7 +406,12 @@ impl Bitv {
#[inline]
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
@ -564,13 +571,14 @@ fn iterate_bits(base: uint, bits: uint, f: &fn(uint) -> bool) -> bool {
/// An iterator for Bitv
pub struct BitvIterator<'self> {
priv bitv: &'self Bitv,
priv next_idx: uint
priv next_idx: uint,
priv end_idx: uint,
}
impl<'self> Iterator<bool> for BitvIterator<'self> {
#[inline]
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;
self.next_idx += 1;
Some(self.bitv.get(idx))
@ -580,11 +588,39 @@ impl<'self> Iterator<bool> for BitvIterator<'self> {
}
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))
}
}
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
/// representation for holding numerical elements.
///

View file

@ -25,7 +25,7 @@
use std::cast;
use std::ptr;
use std::util;
use std::iterator::{FromIterator, Invert};
use std::iterator::{FromIterator, Extendable, Invert};
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> {
fn from_iterator(iterator: &mut T) -> DList<A> {
let mut ret = DList::new();
for iterator.advance |elt| { ret.push_back(elt); }
ret.extend(iterator);
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> {
fn eq(&self, other: &DList<A>) -> bool {
self.len() == other.len() &&

View file

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

View file

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

View file

@ -15,7 +15,7 @@
use std::num;
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
// 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> {
pub fn from_iterator(iter: &mut T) -> TreeMap<K, V> {
fn from_iterator(iter: &mut T) -> TreeMap<K, V> {
let mut map = TreeMap::new();
for iter.advance |(k, v)| {
map.insert(k, v);
}
map.extend(iter);
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> {
pub fn from_iterator(iter: &mut Iter) -> TreeSet<T> {
let mut set = TreeSet::new();
for iter.advance |elem| {
set.insert(elem);
}
set.extend(iter);
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)]
mod test_treemap {

View file

@ -19,7 +19,7 @@ use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
use clone::Clone;
use cmp::{Eq, Equiv};
use hash::Hash;
use iterator::{Iterator, IteratorUtil, FromIterator, Chain};
use iterator::{Iterator, IteratorUtil, FromIterator, Extendable, Chain};
use num;
use option::{None, Option, Some};
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> {
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 mut map = HashMap::with_capacity(lower);
for iter.advance |(k, v)| {
map.insert(k, v);
}
map.extend(iter);
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
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// 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> {
pub fn from_iterator(iter: &mut T) -> HashSet<K> {
fn from_iterator(iter: &mut T) -> HashSet<K> {
let (lower, _) = iter.size_hint();
let mut set = HashSet::with_capacity(lower);
for iter.advance |k| {
set.insert(k);
}
set.extend(iter);
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
/// Building block for Set operation iterators
pub struct EnvFilterIterator<A, Env, I> {

View file

@ -529,7 +529,7 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
#[inline]
fn flat_map_<'r, B, U: Iterator<B>>(self, f: &'r fn(A) -> 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`
@ -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
#[deriving(Clone)]
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`
pub struct Map<'self, A, B, T> {
priv iter: T,
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]
fn next(&mut self) -> Option<B> {
match self.iter.next() {
fn do_map(&self, elt: Option<A>) -> Option<B> {
match elt {
Some(a) => Some((self.f)(a)),
_ => 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]
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> {
#[inline]
fn next_back(&mut self) -> Option<B> {
match self.iter.next_back() {
Some(a) => Some((self.f)(a)),
_ => None
}
let next = self.iter.next_back();
self.do_map(next)
}
}
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
pub struct SkipWhile<'self, A, 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`.
#[deriving(Clone)]
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
pub struct Scan<'self, A, B, T, St> {
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> {
priv iter: T,
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
@ -1259,14 +1372,45 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
#[inline]
fn next(&mut self) -> Option<B> {
loop {
for self.subiter.mut_iter().advance |inner| {
for self.frontiter.mut_iter().advance |inner| {
for inner.advance |x| {
return Some(x)
}
}
match self.iter.next().map_consume(|x| (self.f)(x)) {
None => return None,
next => self.subiter = next,
None => return self.backiter.chain_mut_ref(|it| it.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)
}
impl<'self, A, T: Iterator<A>> Iterator<A> for Peek<'self, A, T> {
impl<'self, A, T> Peek<'self, A, T> {
#[inline]
fn next(&mut self) -> Option<A> {
let next = self.iter.next();
match next {
fn do_peek(&self, elt: Option<A>) -> Option<A> {
match elt {
Some(ref a) => (self.f)(a),
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]
@ -1302,13 +1452,19 @@ impl<'self, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Peek<'self,
#[inline]
fn next_back(&mut self) -> Option<A> {
let next = self.iter.next_back();
self.do_peek(next)
}
}
match next {
Some(ref a) => (self.f)(a),
None => ()
}
impl<'self, A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Peek<'self, A, T> {
#[inline]
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 prelude::*;
use cmp;
use uint;
#[test]
@ -1768,6 +1925,43 @@ mod tests {
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]
fn test_random_access_chain() {
let xs = [1, 2, 3, 4, 5];
@ -1785,5 +1979,71 @@ mod tests {
assert_eq!(it.idx(0).unwrap(), &3);
assert_eq!(it.idx(4).unwrap(), &9);
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 container::{Container, Mutable};
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 num::Zero;
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 {
let (lower, _) = iterator.size_hint();
let mut buf = with_capacity(lower);
for iterator.advance |ch| {
buf.push_char(ch)
}
buf.extend(iterator);
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
impl<'self> Zero for &'self str {
fn zero() -> &'self str { "" }
@ -2503,6 +2514,16 @@ mod tests {
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]
fn test_clear() {
let mut empty = ~"";

View file

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

View file

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