diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index 6e52802578c20..90824a653faad 100644 --- a/src/libextra/bitv.rs +++ b/src/libextra/bitv.rs @@ -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> { + 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 for BitvIterator<'self> { #[inline] fn next(&mut self) -> Option { - 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 for BitvIterator<'self> { } fn size_hint(&self) -> (uint, Option) { - let rem = self.bitv.nbits - self.next_idx; + let rem = self.end_idx - self.next_idx; (rem, Some(rem)) } } +impl<'self> DoubleEndedIterator for BitvIterator<'self> { + #[inline] + fn next_back(&mut self) -> Option { + if self.next_idx != self.end_idx { + self.end_idx -= 1; + Some(self.bitv.get(self.end_idx)) + } else { + None + } + } +} + +impl<'self> RandomAccessIterator for BitvIterator<'self> { + #[inline] + fn indexable(&self) -> uint { + self.end_idx - self.next_idx + } + + #[inline] + fn idx(&self, index: uint) -> Option { + 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. /// diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index b8ba7e58f2a60..88159ce555256 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -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 DoubleEndedIterator for ConsumeIterator { impl> FromIterator for DList { fn from_iterator(iterator: &mut T) -> DList { let mut ret = DList::new(); - for iterator.advance |elt| { ret.push_back(elt); } + ret.extend(iterator); ret } } +impl> Extendable for DList { + fn extend(&mut self, iterator: &mut T) { + for iterator.advance |elt| { self.push_back(elt); } + } +} + impl Eq for DList { fn eq(&self, other: &DList) -> bool { self.len() == other.len() && diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs index dd24a2a9eb96e..1c92a4f34e524 100644 --- a/src/libextra/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -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,17 +191,24 @@ impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> { } impl> FromIterator for PriorityQueue { - pub fn from_iterator(iter: &mut Iter) -> PriorityQueue { + fn from_iterator(iter: &mut Iter) -> PriorityQueue { + let mut q = PriorityQueue::new(); + q.extend(iter); + + q + } +} + +impl> Extendable for PriorityQueue { + fn extend(&mut self, iter: &mut Iter) { let (lower, _) = iter.size_hint(); - let mut q = PriorityQueue::new(); - q.reserve_at_least(lower); + let len = self.capacity(); + self.reserve_at_least(len + lower); for iter.advance |elem| { - q.push(elem); + self.push(elem); } - - q } } diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index 200a409f63c9e..92183f22d3b27 100644 --- a/src/libextra/ringbuf.rs +++ b/src/libextra/ringbuf.rs @@ -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 RingBuf { /// 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 RingBuf { /// 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) { - (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], @@ -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], @@ -314,11 +325,18 @@ impl Eq for RingBuf { impl> FromIterator for RingBuf { fn from_iterator(iterator: &mut T) -> RingBuf { - let mut deq = RingBuf::new(); + let (lower, _) = iterator.size_hint(); + let mut deq = RingBuf::with_capacity(lower); + deq.extend(iterator); + deq + } +} + +impl> Extendable for RingBuf { + fn extend(&mut self, iterator: &mut T) { for iterator.advance |elt| { - deq.push_back(elt); + self.push_back(elt); } - deq } } diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 8c7ace5641246..6148e14b79f3f 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -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,26 +753,36 @@ fn remove(node: &mut Option<~TreeNode>, } impl> FromIterator<(K, V), T> for TreeMap { - pub fn from_iterator(iter: &mut T) -> TreeMap { + fn from_iterator(iter: &mut T) -> TreeMap { let mut map = TreeMap::new(); + map.extend(iter); + map + } +} +impl> Extendable<(K, V), T> for TreeMap { + #[inline] + fn extend(&mut self, iter: &mut T) { for iter.advance |(k, v)| { - map.insert(k, v); + self.insert(k, v); } - - map } } impl> FromIterator for TreeSet { pub fn from_iterator(iter: &mut Iter) -> TreeSet { let mut set = TreeSet::new(); + set.extend(iter); + set + } +} +impl> Extendable for TreeSet { + #[inline] + fn extend(&mut self, iter: &mut Iter) { for iter.advance |elem| { - set.insert(elem); + self.insert(elem); } - - set } } diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index a9a11b611d6d6..e43293f32122a 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -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,15 +618,19 @@ impl Iterator for HashSetConsumeIterator { } impl> FromIterator<(K, V), T> for HashMap { - pub fn from_iterator(iter: &mut T) -> HashMap { + fn from_iterator(iter: &mut T) -> HashMap { let (lower, _) = iter.size_hint(); let mut map = HashMap::with_capacity(lower); + map.extend(iter); + map + } +} +impl> Extendable<(K, V), T> for HashMap { + fn extend(&mut self, iter: &mut T) { for iter.advance |(k, v)| { - map.insert(k, v); + self.insert(k, v); } - - map } } @@ -771,15 +775,19 @@ impl HashSet { } impl> FromIterator for HashSet { - pub fn from_iterator(iter: &mut T) -> HashSet { + fn from_iterator(iter: &mut T) -> HashSet { let (lower, _) = iter.size_hint(); let mut set = HashSet::with_capacity(lower); + set.extend(iter); + set + } +} +impl> Extendable for HashSet { + fn extend(&mut self, iter: &mut T) { for iter.advance |k| { - set.insert(k); + self.insert(k); } - - set } } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 6828de5162284..9fe865333a215 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -529,7 +529,7 @@ impl> IteratorUtil for T { #[inline] fn flat_map_<'r, B, U: Iterator>(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> Iterator for Cycle { } } +impl> RandomAccessIterator for Cycle { + #[inline] + fn indexable(&self) -> uint { + if self.orig.indexable() > 0 { + uint::max_value + } else { + 0 + } + } + + #[inline] + fn idx(&self, index: uint) -> Option { + 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 { @@ -924,20 +948,44 @@ impl, U: Iterator> Iterator<(A, B)> for Zip { } } +impl, U: RandomAccessIterator> +RandomAccessIterator<(A, B)> for Zip { + #[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> Iterator for Map<'self, A, B, T> { +impl<'self, A, B, T> Map<'self, A, B, T> { #[inline] - fn next(&mut self) -> Option { - match self.iter.next() { + fn do_map(&self, elt: Option) -> Option { + match elt { Some(a) => Some((self.f)(a)), _ => None } } +} + +impl<'self, A, B, T: Iterator> Iterator for Map<'self, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + self.do_map(next) + } #[inline] fn size_hint(&self) -> (uint, Option) { @@ -949,10 +997,21 @@ impl<'self, A, B, T: DoubleEndedIterator> DoubleEndedIterator for Map<'self, A, B, T> { #[inline] fn next_back(&mut self) -> Option { - 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> RandomAccessIterator +for Map<'self, A, B, T> { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable() + } + + #[inline] + fn idx(&self, index: uint) -> Option { + self.do_map(self.iter.idx(index)) } } @@ -1069,6 +1128,21 @@ impl> Iterator<(uint, A)> for Enumerate { } } +impl> RandomAccessIterator<(uint, A)> for Enumerate { + #[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> Iterator for Skip { } } +impl> RandomAccessIterator for Skip { + #[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 { + 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 { @@ -1223,6 +1318,23 @@ impl> Iterator for Take { } } +impl> RandomAccessIterator for Take { + #[inline] + fn indexable(&self) -> uint { + cmp::min(self.iter.indexable(), self.n) + } + + #[inline] + fn idx(&self, index: uint) -> Option { + 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, St> Iterator 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, + priv frontiter: Option, + priv backiter: Option, } impl<'self, A, T: Iterator, B, U: Iterator> Iterator for @@ -1259,14 +1372,45 @@ impl<'self, A, T: Iterator, B, U: Iterator> Iterator for #[inline] fn next(&mut self) -> Option { 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) { + 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, + B, U: DoubleEndedIterator> DoubleEndedIterator + for FlatMap<'self, A, T, U> { + #[inline] + fn next_back(&mut self) -> Option { + 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> Iterator for Peek<'self, A, T> { +impl<'self, A, T> Peek<'self, A, T> { #[inline] - fn next(&mut self) -> Option { - let next = self.iter.next(); - - match next { + fn do_peek(&self, elt: Option) -> Option { + match elt { Some(ref a) => (self.f)(a), None => () } - next + elt + } +} + +impl<'self, A, T: Iterator> Iterator for Peek<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + self.do_peek(next) } #[inline] @@ -1302,13 +1452,19 @@ impl<'self, A, T: DoubleEndedIterator> DoubleEndedIterator for Peek<'self, #[inline] fn next_back(&mut self) -> Option { let next = self.iter.next_back(); + self.do_peek(next) + } +} - match next { - Some(ref a) => (self.f)(a), - None => () - } +impl<'self, A, T: RandomAccessIterator> RandomAccessIterator for Peek<'self, A, T> { + #[inline] + fn indexable(&self) -> uint { + self.iter.indexable() + } - next + #[inline] + fn idx(&self, index: uint) -> Option { + 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: 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); } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 2aa5f586dd8f1..fff859321fbe6 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -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,10 +2324,20 @@ impl> FromIterator for ~str { fn from_iterator(iterator: &mut T) -> ~str { let (lower, _) = iterator.size_hint(); let mut buf = with_capacity(lower); + buf.extend(iterator); + buf + } +} + +impl> Extendable 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| { - buf.push_char(ch) + self.push_char(ch) } - buf } } @@ -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 = ~""; diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index 4665f36134011..6a0554a8c8d43 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -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,14 +155,18 @@ impl TrieMap { } impl> FromIterator<(uint, T), Iter> for TrieMap { - pub fn from_iterator(iter: &mut Iter) -> TrieMap { + fn from_iterator(iter: &mut Iter) -> TrieMap { let mut map = TrieMap::new(); + map.extend(iter); + map + } +} +impl> Extendable<(uint, T), Iter> for TrieMap { + fn extend(&mut self, iter: &mut Iter) { for iter.advance |(k, v)| { - map.insert(k, v); + self.insert(k, v); } - - map } } @@ -222,14 +226,18 @@ impl TrieSet { } impl> FromIterator for TrieSet { - pub fn from_iterator(iter: &mut Iter) -> TrieSet { + fn from_iterator(iter: &mut Iter) -> TrieSet { let mut set = TrieSet::new(); + set.extend(iter); + set + } +} +impl> Extendable for TrieSet { + fn extend(&mut self, iter: &mut Iter) { for iter.advance |elem| { - set.insert(elem); + self.insert(elem); } - - set } } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index fdfe357ae5106..cfd28fcfc5eaa 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2106,7 +2106,8 @@ macro_rules! iterator { #[inline] fn size_hint(&self) -> (uint, Option) { - let exact = self.indexable(); + let diff = (self.end as uint) - (self.ptr as uint); + let exact = diff / sys::nonzero_size_of::(); (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::() - } +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>; 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>; /// An iterator that moves out of a vector.