From 4b2931c90fbe152ca1dd3111985057778dad1ba9 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 20 Jul 2013 03:11:28 +0200 Subject: [PATCH 01/11] iterator: implement DoubleEndedIterator for FlatMap --- src/libstd/iterator.rs | 49 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 6828de516228..33d863f3716e 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` @@ -1251,7 +1251,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 +1260,35 @@ 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, + } + } + } +} + +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, } } } @@ -1768,6 +1790,23 @@ mod tests { assert_eq!(it.next_back(), None) } + #[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]; From 5d4af58c1d2abc0895d170185796e837f37b16cb Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Sat, 20 Jul 2013 17:10:00 +0200 Subject: [PATCH 02/11] iterator: implement size_hint() for FlatMap --- src/libstd/iterator.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 33d863f3716e..87390781802c 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -1271,6 +1271,16 @@ impl<'self, A, T: Iterator, B, U: Iterator> Iterator for } } } + + #[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, From 630627c3d43c17a6a657e7b91b754c45929a5bf6 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 29 Jul 2013 17:44:45 +0200 Subject: [PATCH 03/11] std: Implement RandomAccessIterator for iterator adaptors Implement RAI where possible for iterator adaptors such as Map, Enumerate, Skip, Take, Zip, Cycle (all of the requiring that the adapted iterator also implements RAI). --- src/libstd/iterator.rs | 160 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 142 insertions(+), 18 deletions(-) diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 87390781802c..a432546f8d09 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -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, @@ -1311,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] @@ -1334,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)) } } From 66fccdb2958fef88e00236497aec5e0f99fe7d02 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 29 Jul 2013 19:18:45 +0200 Subject: [PATCH 04/11] std: Tests for RandomAccessIterators --- src/libstd/iterator.rs | 87 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index a432546f8d09..9fe865333a21 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -1532,6 +1532,7 @@ mod tests { use super::*; use prelude::*; + use cmp; use uint; #[test] @@ -1924,6 +1925,26 @@ 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]; @@ -1958,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); } } From 2ff84124f0d39b20f49ce04f71d31322cdf1a327 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 30 Jul 2013 00:31:44 +0200 Subject: [PATCH 05/11] std: Remove RandomAccessIterator impl for VecMutIterator The RandomAccessIterator implementation is not sound for the mutable vec iterator, and makes it easy to duplicate &mut element pointers. --- src/libstd/vec.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index fdfe357ae510..ca752490faa8 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)) } } @@ -2139,8 +2140,8 @@ macro_rules! random_access_iterator { 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::() + let (exact, _) = self.size_hint(); + exact } fn idx(&self, index: uint) -> Option<$elem> { @@ -2181,7 +2182,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. From 2f10d1e295d0ba0b2ce2777443fbfbeb9711787d Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 29 Jul 2013 21:22:54 +0200 Subject: [PATCH 06/11] extra: Implement DoubleEnded and RandomAccess iterators for bitv --- src/libextra/bitv.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index 6e52802578c2..914aa20792f1 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,7 @@ 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} } /// Returns true if all bits are 0 @@ -564,13 +566,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 +583,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. /// From f68621326ec295de6fd383a5230b807049ec4820 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Mon, 29 Jul 2013 20:16:26 +0200 Subject: [PATCH 07/11] extra: Implement RandomAccessIterator for RingBuf --- src/libextra/ringbuf.rs | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index 200a409f63c9..90f37cbf526f 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}; 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], From f8ae526f707c9a9e0540b80209838d2e75dc960b Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 30 Jul 2013 02:06:49 +0200 Subject: [PATCH 08/11] extra: Implement iterator::Extendable --- src/libextra/dlist.rs | 10 ++++++++-- src/libextra/priority_queue.rs | 25 ++++++++++++++++--------- src/libextra/ringbuf.rs | 17 ++++++++++++----- src/libextra/treemap.rs | 34 ++++++++++++++++++++++------------ 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index b8ba7e58f2a6..88159ce55525 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 dd24a2a9eb96..1c92a4f34e52 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,20 +191,27 @@ impl<'self, T> Iterator<&'self T> for PriorityQueueIterator<'self, T> { } impl> FromIterator for PriorityQueue { - pub fn from_iterator(iter: &mut Iter) -> PriorityQueue { - let (lower, _) = iter.size_hint(); - + fn from_iterator(iter: &mut Iter) -> PriorityQueue { let mut q = PriorityQueue::new(); - q.reserve_at_least(lower); - - for iter.advance |elem| { - q.push(elem); - } + q.extend(iter); q } } +impl> Extendable for PriorityQueue { + 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; diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index 90f37cbf526f..92183f22d3b2 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, RandomAccessIterator}; +use std::iterator::{FromIterator, Invert, RandomAccessIterator, Extendable}; use container::Deque; @@ -325,14 +325,21 @@ impl Eq for RingBuf { impl> FromIterator for RingBuf { fn from_iterator(iterator: &mut T) -> RingBuf { - 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> Extendable for RingBuf { + fn extend(&mut self, iterator: &mut T) { + for iterator.advance |elt| { + self.push_back(elt); + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 8c7ace564124..6148e14b79f3 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,29 +753,39 @@ 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(); - - for iter.advance |(k, v)| { - map.insert(k, v); - } - + map.extend(iter); map } } +impl> Extendable<(K, V), T> for TreeMap { + #[inline] + fn extend(&mut self, iter: &mut T) { + for iter.advance |(k, v)| { + self.insert(k, v); + } + } +} + impl> FromIterator for TreeSet { pub fn from_iterator(iter: &mut Iter) -> TreeSet { let mut set = TreeSet::new(); - - for iter.advance |elem| { - set.insert(elem); - } - + set.extend(iter); set } } +impl> Extendable for TreeSet { + #[inline] + fn extend(&mut self, iter: &mut Iter) { + for iter.advance |elem| { + self.insert(elem); + } + } +} + #[cfg(test)] mod test_treemap { From 5307d3674e2df2baef0e37125a98227590fc43d2 Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 30 Jul 2013 02:17:17 +0200 Subject: [PATCH 09/11] std: Implement Extendable for hashmap, str and trie --- src/libstd/hashmap.rs | 34 +++++++++++++++++++++------------- src/libstd/str.rs | 29 +++++++++++++++++++++++++---- src/libstd/trie.rs | 34 +++++++++++++++++++++------------- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index a9a11b611d6d..e43293f32122 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,18 +618,22 @@ 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); - - for iter.advance |(k, v)| { - map.insert(k, v); - } - + map.extend(iter); map } } +impl> Extendable<(K, V), T> for HashMap { + 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 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); - - for iter.advance |k| { - set.insert(k); - } - + set.extend(iter); set } } +impl> Extendable for HashSet { + 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 { diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 2aa5f586dd8f..fff859321fbe 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,13 +2324,23 @@ impl> FromIterator 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> 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| { + 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 = ~""; diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index 4665f3613401..6a0554a8c8d4 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,17 +155,21 @@ 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(); - - for iter.advance |(k, v)| { - map.insert(k, v); - } - + map.extend(iter); map } } +impl> Extendable<(uint, T), Iter> for TrieMap { + 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> FromIterator 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> Extendable for TrieSet { + fn extend(&mut self, iter: &mut Iter) { + for iter.advance |elem| { + self.insert(elem); + } + } +} + struct TrieNode { count: uint, children: [Child, ..SIZE] From ae09d95160919f8801caa22e2867e9680e6cb05b Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 30 Jul 2013 02:48:40 +0200 Subject: [PATCH 10/11] extra: Add .rev_iter() for bitv --- src/libextra/bitv.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index 914aa20792f1..90824a653faa 100644 --- a/src/libextra/bitv.rs +++ b/src/libextra/bitv.rs @@ -409,6 +409,11 @@ impl Bitv { 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 pub fn is_false(&self) -> bool { match self.rep { From 99490ad5ba61b2ee69c2cdd70c70857eaf0b895f Mon Sep 17 00:00:00 2001 From: blake2-ppc Date: Tue, 30 Jul 2013 02:52:01 +0200 Subject: [PATCH 11/11] std: Remove macro in vec that's only used once --- src/libstd/vec.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index ca752490faa8..cfd28fcfc5ea 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2135,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 (exact, _) = self.size_hint(); - exact - } +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 } } } @@ -2166,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> {