diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 9131c4faa8021..236d53ad5d8f6 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -73,7 +73,10 @@ syn keyword rustTrait Char syn keyword rustTrait Clone DeepClone syn keyword rustTrait Eq ApproxEq Ord TotalEq TotalOrd Ordering Equiv syn keyword rustEnumVariant Less Equal Greater -syn keyword rustTrait Container Mutable Map MutableMap Set MutableSet +syn keyword rustTrait Container NewContainer Mutable +syn keyword rustTrait Seq MutableSeq +syn keyword rustTrait Map MutableMap +syn keyword rustTrait Set MutableSet syn keyword rustTrait Default syn keyword rustTrait Hash syn keyword rustTrait FromStr diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 7da92704ceb01..3f6adf87b5b42 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -132,6 +132,11 @@ impl Container for DList { } } +impl NewContainer for DList { + #[inline] + fn with_capacity(_capacity: uint) -> DList { DList::new() } +} + impl Mutable for DList { /// Remove all elements from the DList /// diff --git a/src/libextra/flate.rs b/src/libextra/flate.rs index 5227cb18e6ea2..b05585b36d3a9 100644 --- a/src/libextra/flate.rs +++ b/src/libextra/flate.rs @@ -98,6 +98,7 @@ pub fn inflate_bytes_zlib(bytes: &[u8]) -> ~[u8] { #[cfg(test)] mod tests { use super::*; + use container::MutableSeq; use std::rand; use std::rand::Rng; @@ -112,7 +113,7 @@ mod tests { 20.times(|| { let mut input = ~[]; 2000.times(|| { - input.push_all(r.choose(words)); + input.push_all(r.choose(words).move_iter()); }); debug!("de/inflate of {} bytes of random word-sequences", input.len()); diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs index 77d1c5cdcf49e..b521b80507176 100644 --- a/src/libextra/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -28,6 +28,14 @@ impl Container for PriorityQueue { fn len(&self) -> uint { self.data.len() } } +impl NewContainer for PriorityQueue { + /// Create an empty Priority Queue with capacity `capacity` + #[inline] + fn with_capacity(capacity: uint) -> PriorityQueue { + PriorityQueue::with_capacity(capacity) + } +} + impl Mutable for PriorityQueue { /// Drop all items from the queue fn clear(&mut self) { self.data.truncate(0) } @@ -112,7 +120,12 @@ impl PriorityQueue { } /// Create an empty PriorityQueue - pub fn new() -> PriorityQueue { PriorityQueue{data: ~[],} } + pub fn new() -> PriorityQueue { PriorityQueue{data: ~[]} } + + /// Create an empty PriorityQueue + pub fn with_capacity(capacity: uint) -> PriorityQueue { + PriorityQueue{data: vec::with_capacity(capacity)} + } /// Create a PriorityQueue from a vector (heapify) pub fn from_vec(xs: ~[T]) -> PriorityQueue { diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index 19e293c94a219..e36f8a779dbf9 100644 --- a/src/libextra/ringbuf.rs +++ b/src/libextra/ringbuf.rs @@ -35,6 +35,12 @@ impl Container for RingBuf { fn len(&self) -> uint { self.nelts } } +impl NewContainer for RingBuf { + fn new() -> RingBuf { RingBuf::new() } + + fn with_capacity(capacity: uint) -> RingBuf { RingBuf::with_capacity(capacity) } +} + impl Mutable for RingBuf { /// Clear the RingBuf, removing all values. fn clear(&mut self) { diff --git a/src/libextra/smallintmap.rs b/src/libextra/smallintmap.rs index 649ed281f87e2..d447380fda27a 100644 --- a/src/libextra/smallintmap.rs +++ b/src/libextra/smallintmap.rs @@ -37,6 +37,13 @@ impl Container for SmallIntMap { } } +impl NewContainer for SmallIntMap { + /// Create an empty SmallIntMap with capacity `capacity` + fn with_capacity(capacity: uint) -> SmallIntMap { + SmallIntMap::with_capacity(capacity) + } +} + impl Mutable for SmallIntMap { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { self.v.clear() } @@ -113,6 +120,11 @@ impl SmallIntMap { /// Create an empty SmallIntMap pub fn new() -> SmallIntMap { SmallIntMap{v: ~[]} } + /// Create an empty SmallIntMap with capacity `capacity` + pub fn with_capacity(capacity: uint) -> SmallIntMap { + SmallIntMap{v: vec::with_capacity(capacity)} + } + pub fn get<'a>(&'a self, key: &uint) -> &'a V { self.find(key).expect("key not present") } diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs index bba26a16d4dad..c0c68cb014b1e 100644 --- a/src/libextra/sort.rs +++ b/src/libextra/sort.rs @@ -58,8 +58,8 @@ pub fn merge_sort(v: &[T], le: Le) -> ~[T] { b_ix += 1; } } - rs.push_all(a.slice(a_ix, a_len)); - rs.push_all(b.slice(b_ix, b_len)); + rs.push_all(a.slice(a_ix, a_len).clone_iter()); + rs.push_all(b.slice(b_ix, b_len).clone_iter()); rs } } diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs index eac450d9562f2..673f5a11b13fd 100644 --- a/src/libextra/terminfo/parm.rs +++ b/src/libextra/terminfo/parm.rs @@ -248,7 +248,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) let flags = Flags::new(); let res = format(stack.pop(), FormatOp::from_char(cur), flags); if res.is_err() { return res } - output.push_all(res.unwrap()) + output.push_all(res.unwrap().move_iter()) } else { return Err(~"stack is empty") }, ':'|'#'|' '|'.'|'0'..'9' => { let mut flags = Flags::new(); @@ -343,7 +343,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) (_,'d')|(_,'o')|(_,'x')|(_,'X')|(_,'s') => if stack.len() > 0 { let res = format(stack.pop(), FormatOp::from_char(cur), *flags); if res.is_err() { return res } - output.push_all(res.unwrap()); + output.push_all(res.unwrap().move_iter()); old_state = state; // will cause state to go to Nothing } else { return Err(~"stack is empty") }, (FormatStateFlags,'#') => { diff --git a/src/libextra/time.rs b/src/libextra/time.rs index 6204f9f4ce0b1..1cff1c4ce7e2e 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -939,7 +939,7 @@ pub fn strftime(format: &str, tm: &Tm) -> ~str { '%' => { rdr.read(b); let s = parse_type(b[0] as char, tm); - buf.push_all(s.as_bytes()); + buf.push_all(s.into_bytes().move_iter()); } ch => buf.push(ch as u8) } diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 7c41104814978..8730fe5f8f029 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -80,6 +80,10 @@ impl Container for TreeMap { fn is_empty(&self) -> bool { self.root.is_none() } } +impl NewContainer for TreeMap { + fn with_capacity(_capacity: uint) -> TreeMap { TreeMap::new() } +} + impl Mutable for TreeMap { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { @@ -441,6 +445,10 @@ impl Container for TreeSet { fn is_empty(&self) -> bool { self.map.is_empty() } } +impl NewContainer for TreeSet { + fn with_capacity(_capacity: uint) -> TreeSet { TreeSet::new() } +} + impl Mutable for TreeSet { /// Clear the set, removing all values. #[inline] diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index d67277289d431..55a5aaf64796b 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -998,9 +998,9 @@ fn link_args(sess: Session, let mut args = ~[stage]; // FIXME (#9639): This needs to handle non-utf8 paths - args.push_all([ - ~"-o", out_filename.as_str().unwrap().to_owned(), - obj_filename.as_str().unwrap().to_owned()]); + args.push(~"-o"); + args.push(out_filename.as_str().unwrap().to_owned()); + args.push(obj_filename.as_str().unwrap().to_owned()); // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main @@ -1046,9 +1046,9 @@ fn link_args(sess: Session, } if sess.targ_cfg.os == abi::OsFreebsd { - args.push_all([~"-L/usr/local/lib", - ~"-L/usr/local/lib/gcc46", - ~"-L/usr/local/lib/gcc44"]); + args.push(~"-L/usr/local/lib"); + args.push(~"-L/usr/local/lib/gcc46"); + args.push(~"-L/usr/local/lib/gcc44"); } // Stack growth requires statically linking a __morestack function @@ -1057,11 +1057,11 @@ fn link_args(sess: Session, // FIXME (#2397): At some point we want to rpath our guesses as to // where extern libraries might live, based on the // addl_lib_search_paths - args.push_all(rpath::get_rpath_flags(sess, out_filename)); + args.push_all(rpath::get_rpath_flags(sess, out_filename).move_iter()); // Finally add all the linker arguments provided on the command line along // with any #[link_args] attributes found inside the crate - args.push_all(sess.opts.linker_args); + args.push_all(sess.opts.linker_args.clone_iter()); for arg in cstore::get_used_link_args(sess.cstore).iter() { args.push(arg.clone()); } diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index dae4a9df3da96..2555e679143fb 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -32,9 +32,9 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] { let mut flags = ~[]; if sess.targ_cfg.os == abi::OsFreebsd { - flags.push_all([~"-Wl,-rpath,/usr/local/lib/gcc46", - ~"-Wl,-rpath,/usr/local/lib/gcc44", - ~"-Wl,-z,origin"]); + flags.push(~"-Wl,-rpath,/usr/local/lib/gcc46"); + flags.push(~"-Wl,-rpath,/usr/local/lib/gcc44"); + flags.push(~"-Wl,-z,origin"); } debug!("preparing the RPATH!"); @@ -49,7 +49,7 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] { let rpaths = get_rpaths(os, sysroot, output, libs, sess.opts.target_triple); - flags.push_all(rpaths_to_flags(rpaths)); + flags.push_all(rpaths_to_flags(rpaths).move_iter()); flags } @@ -105,8 +105,8 @@ fn get_rpaths(os: abi::Os, log_rpaths("fallback", fallback_rpaths); let mut rpaths = rel_rpaths; - rpaths.push_all(abs_rpaths); - rpaths.push_all(fallback_rpaths); + rpaths.push_all(abs_rpaths.move_iter()); + rpaths.push_all(fallback_rpaths.move_iter()); // Remove duplicates let rpaths = minimize_rpaths(rpaths); diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index a40f8183e1904..1934094d8d0ad 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -81,7 +81,7 @@ impl fold::ast_fold for StandardLibraryInjector { }); } - vis.push_all(crate.module.view_items); + vis.push_all(crate.module.view_items.clone_iter()); let mut new_module = ast::_mod { view_items: vis, ..crate.module.clone() diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 5230a5c81b223..2ea46e0d288c8 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -793,7 +793,7 @@ pub fn trans_args(cx: @mut Block, } } ArgVals(vs) => { - llargs.push_all(vs); + llargs.push_all(vs.clone_iter()); } } diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 17620a81e51a7..1af177cdcb973 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -60,7 +60,7 @@ pub fn type_of_rust_fn(cx: &mut CrateContext, atys.push(Type::opaque_box(cx).ptr_to()); // ... then explicit args. - atys.push_all(type_of_explicit_args(cx, inputs)); + atys.push_all(type_of_explicit_args(cx, inputs).move_iter()); // Use the output as the actual return value if it's immediate. if !use_out_pointer && !ty::type_is_voidish(cx.tcx, output) { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 799f1a879da73..9d47d50579b49 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -957,8 +957,8 @@ pub fn compare_impl_method(tcx: ty::ctxt, } // Add in the normal arguments. - trait_fn_args.push_all(trait_m.fty.sig.inputs); - impl_fn_args.push_all(impl_m.fty.sig.inputs); + trait_fn_args.push_all(trait_m.fty.sig.inputs.clone_iter()); + impl_fn_args.push_all(impl_m.fty.sig.inputs.clone_iter()); // Create a bare fn type for trait/impl that includes self argument let trait_fty = diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 343808c2fa7af..86d2c50c6fbda 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -322,7 +322,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, let mut new_type_param_defs = ~[]; let substd_type_param_defs = trait_ty_generics.type_param_defs.subst(tcx, &substs); - new_type_param_defs.push_all(*substd_type_param_defs); + new_type_param_defs.push_all(substd_type_param_defs.clone_iter()); // add in the "self" type parameter let self_trait_def = get_trait_def(ccx, local_def(trait_id)); @@ -338,7 +338,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, // add in the type parameters from the method let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs); - new_type_param_defs.push_all(*substd_type_param_defs); + new_type_param_defs.push_all(substd_type_param_defs.clone_iter()); debug!("static method {} type_param_defs={} ty={}, substs={}", m.def_id.repr(tcx), diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0c703e780f19b..043f2a3955f4e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -427,7 +427,7 @@ impl<'a> SourceCollector<'a> { // read everything loop { match r.read(buf) { - Some(n) => contents.push_all(buf.slice_to(n)), + Some(n) => contents.push_all(buf.slice_to(n).clone_iter()), None => break } } diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index d9c3cf8031695..6cb5971ea0d47 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -271,7 +271,7 @@ pub fn unindent(s: &str) -> ~str { match lines { [head, .. tail] => { let mut unindented = ~[ head.trim() ]; - unindented.push_all(tail.map(|&line| { + unindented.push_all(tail.iter().map(|&line| { if line.is_whitespace() { line } else { diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index a6b1088335c63..d8f94be407092 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -462,7 +462,7 @@ pub fn versionize(p: &Path, v: &Version) -> Path { let mut q = q.to_owned(); q.push('-' as u8); let vs = v.to_str(); - q.push_all(vs.as_bytes()); + q.push_all(vs.into_bytes().move_iter()); p.with_filename(q) } diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 7b1d29b664b6d..da679a1494651 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -30,6 +30,15 @@ pub fn capacity(v: @[T]) -> uint { } } +/// Creates an immutable managed vector with a capacity of `capacity` +pub fn with_capacity(capacity: uint) -> @[T] { + let mut av = @[]; + unsafe { + raw::reserve(&mut av, capacity); + } + av +} + /** * Builds a vector by calling a provided function with an argument * function that pushes an element to the back of a vector. @@ -44,8 +53,7 @@ pub fn capacity(v: @[T]) -> uint { */ #[inline] pub fn build(size: Option, builder: |push: |v: A||) -> @[A] { - let mut vec = @[]; - unsafe { raw::reserve(&mut vec, size.unwrap_or(4)); } + let mut vec = with_capacity(size.unwrap_or(4)); builder(|x| unsafe { raw::push(&mut vec, x) }); vec } @@ -110,14 +118,13 @@ pub fn from_elem(n_elts: uint, t: T) -> @[T] { * elements from an owned vector. */ pub fn to_managed_move(v: ~[T]) -> @[T] { - let mut av = @[]; - unsafe { - raw::reserve(&mut av, v.len()); - for x in v.move_iter() { + let mut av = with_capacity(v.len()); + for x in v.move_iter() { + unsafe { raw::push(&mut av, x); } - av } + av } /** diff --git a/src/libstd/container.rs b/src/libstd/container.rs index c91a53f966388..374ce576da843 100644 --- a/src/libstd/container.rs +++ b/src/libstd/container.rs @@ -10,7 +10,8 @@ //! Container traits -use option::Option; +use iter::Iterator; +use option::{Option, Some, None}; /// A trait to represent the abstract idea of a container. The only concrete /// knowledge known is the number of elements contained within. @@ -25,12 +26,82 @@ pub trait Container { } } +/// A trait to represent constructable containers +pub trait NewContainer { + /// Creates a new container. + fn new() -> Self { NewContainer::with_capacity(0) } + + /// Creates a new container with a capacity of `capacity`. + fn with_capacity(capacity: uint) -> Self; +} + /// A trait to represent mutable containers pub trait Mutable: Container { /// Clear the container, removing all values. fn clear(&mut self); } +/// A trait to represent an order sequence of values, where values are looked +/// up by their position. +pub trait Seq: Container { +} + +/// A trait that provides basic operations to modify the contents of a +/// sequence. +pub trait MutableSeq: Seq + Mutable { + /// Append an element to a sequence + fn push(&mut self, value: T); + + /// Moving all elements into the current sequence. This does not copy any + /// elements. + /// + /// # Example + /// + /// ```rust + /// let mut a = ~[~1]; + /// a.push_all((~[~2, ~3, ~4]).move_iter()); + /// assert!(a == ~[~1, ~2, ~3, ~4]); + /// ``` + #[inline] + fn push_all>(&mut self, mut iter: Iter) { + for x in &mut iter { + self.push(x); + } + } + + /// Remove the last element from a sequence and return it, failing if it is + /// empty + #[inline] + fn pop(&mut self) -> T { + self.pop_opt().expect("pop: empty sequence") + } + + /// Remove the last element from a sequence and return it, or `None` if it + /// is empty + fn pop_opt(&mut self) -> Option; + + /// Removes the first element from a sequence and return it + #[inline] + fn shift(&mut self) -> T { + self.shift_opt().expect("shift: empty sequence") + } + + /// Removes the first element from a sequence and return it, or `None` if + /// it is empty + fn shift_opt(&mut self) -> Option; + + /// Prepend an element to the sequence + fn unshift(&mut self, x: T); + + /// Insert an element at position i within v, shifting all + /// elements after position i one position to the right. + fn insert(&mut self, i: uint, x: T); + + /// Remove and return the element at position i within v, shifting + /// all elements after position i one position to the left. + fn remove(&mut self, i: uint) -> T; +} + /// A map is a key-value store where values may be looked up by their keys. This /// trait provides basic operations to operate on these stores. pub trait Map: Container { diff --git a/src/libstd/either.rs b/src/libstd/either.rs index 6d152d8c179a8..b5e8af1ebb73c 100644 --- a/src/libstd/either.rs +++ b/src/libstd/either.rs @@ -15,7 +15,7 @@ use option::{Some, None}; use option; use clone::Clone; -use container::Container; +use container::{Container, MutableSeq}; use cmp::Eq; use iter::{Iterator, FilterMap}; use result::Result; diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 335e77c647803..a87bac88c9afb 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -13,7 +13,7 @@ //! The tables use a keyed hash with new random keys generated for each container, so the ordering //! of a set of keys in a hash table is randomized. -use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; +use container::{Container, NewContainer, Mutable, Map, MutableMap, Set, MutableSet}; use clone::Clone; use cmp::{Eq, Equiv}; use default::Default; @@ -258,6 +258,16 @@ impl Container for HashMap { fn len(&self) -> uint { self.size } } +impl NewContainer for HashMap { + fn new() -> HashMap { + HashMap::new() + } + + fn with_capacity(capacity: uint) -> HashMap { + HashMap::with_capacity(capacity) + } +} + impl Mutable for HashMap { /// Clear the map, removing all key-value pairs. fn clear(&mut self) { @@ -649,6 +659,16 @@ impl Container for HashSet { fn len(&self) -> uint { self.map.len() } } +impl NewContainer for HashSet { + fn new() -> HashSet { + HashSet::new() + } + + fn with_capacity(capacity: uint) -> HashSet { + HashSet::with_capacity(capacity) + } +} + impl Mutable for HashSet { /// Clear the set, removing all values. fn clear(&mut self) { self.map.clear() } diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index a7361fa8c373c..730b3f5096dc6 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -13,6 +13,7 @@ // XXX: Not sure how this should be structured // XXX: Iteration should probably be considered separately +use container::MutableSeq; use iter::Iterator; use option::Option; use io::Reader; diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index a1465ca7b33a0..885c7981c0cfb 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -47,6 +47,7 @@ particular bits of it, etc. use c_str::ToCStr; use clone::Clone; +use container::MutableSeq; use iter::Iterator; use super::{Reader, Writer, Seek}; use super::{SeekStyle, Read, Write, Open, IoError, Truncate, diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index efb55a436eaf4..4c4b69fc1d690 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -38,6 +38,16 @@ impl MemWriter { } } +impl NewContainer for MemWriter { + fn new() -> MemWriter { + MemWriter::new() + } + + fn with_capacity(n: uint) -> MemWriter { + MemWriter::with_capacity(n) + } +} + impl Writer for MemWriter { fn write(&mut self, buf: &[u8]) { // Make sure the internal buffer is as least as big as where we @@ -61,7 +71,7 @@ impl Writer for MemWriter { vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left); } if right.len() > 0 { - self.buf.push_all(right); + self.buf.push_all(right.clone_iter()); } // Bump us forward diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index c0bdc2a201435..a4739f93b6d28 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -264,7 +264,7 @@ Out of scope use cast; use condition::Guard; -use container::Container; +use container::{Container, MutableSeq}; use int; use iter::Iterator; use option::{Option, Some, None}; @@ -276,6 +276,7 @@ use to_str::ToStr; use uint; use unstable::finally::Finally; use vec::{OwnedVector, MutableVector, ImmutableVector, OwnedCopyableVector}; +use vec::ImmutableCopyableVector; use vec; // Reexports @@ -1079,12 +1080,12 @@ pub trait Buffer: Reader { let available = self.fill(); match available.iter().position(|&b| b == byte) { Some(i) => { - res.push_all(available.slice_to(i + 1)); + res.push_all(available.slice_to(i + 1).clone_iter()); used = i + 1; break } None => { - res.push_all(available); + res.push_all(available.clone_iter()); used = available.len(); } } diff --git a/src/libstd/io/native/file.rs b/src/libstd/io/native/file.rs index bd618dd6f0f4a..0a24775a31b85 100644 --- a/src/libstd/io/native/file.rs +++ b/src/libstd/io/native/file.rs @@ -13,6 +13,7 @@ #[allow(non_camel_case_types)]; use c_str::CString; +use container::MutableSeq; use io::IoError; use io; use libc::c_int; diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 8e678ab66b25e..54271145532e5 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -11,7 +11,7 @@ #[allow(missing_doc)]; use clone::Clone; -use container::Container; +use container::{Container, MutableSeq}; use std::cmp::{Ord, Eq}; use ops::{Add, Sub, Mul, Div, Rem, Neg}; use option::{None, Option, Some}; @@ -19,7 +19,6 @@ use char; use str::{StrSlice}; use str; use vec::{CopyableVector, ImmutableVector, MutableVector}; -use vec::OwnedVector; use num::{NumCast, Zero, One, cast, pow_with_uint, Integer}; use num::{Round, Float, FPNaN, FPInfinite}; diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs index 53948dc83099f..ecb6c57269b9e 100644 --- a/src/libstd/path/mod.rs +++ b/src/libstd/path/mod.rs @@ -64,7 +64,7 @@ debug!("path exists: {}", b); */ -use container::Container; +use container::{Container, MutableSeq}; use c_str::CString; use clone::Clone; use fmt; @@ -74,8 +74,8 @@ use str; use str::{OwnedStr, Str, StrSlice}; use to_str::ToStr; use vec; -use vec::{CopyableVector, OwnedCopyableVector, OwnedVector, Vector}; -use vec::{ImmutableEqVector, ImmutableVector}; +use vec::{CopyableVector, OwnedVector, Vector}; +use vec::{ImmutableEqVector, ImmutableVector, ImmutableCopyableVector}; /// Typedef for POSIX file paths. /// See `posix::Path` for more info. @@ -307,15 +307,15 @@ pub trait GenericPath: Clone + GenericPathUnsafe { let extension = self::null_byte::cond.raise(ext); assert!(!contains_nul(extension)); v = vec::with_capacity(name.len() + extension.len() + 1); - v.push_all(name); + v.push_all(name.clone_iter()); v.push(dot); - v.push_all(extension); + v.push_all(extension.clone_iter()); } else { let extension = extension.container_as_bytes(); v = vec::with_capacity(name.len() + extension.len() + 1); - v.push_all(name); + v.push_all(name.clone_iter()); v.push(dot); - v.push_all(extension); + v.push_all(extension.clone_iter()); } Some(v) } @@ -330,13 +330,13 @@ pub trait GenericPath: Clone + GenericPathUnsafe { let extension = self::null_byte::cond.raise(ext); assert!(!contains_nul(extension)); v = vec::with_capacity(idx + extension.len() + 1); - v.push_all(name.slice_to(idx+1)); - v.push_all(extension); + v.push_all(name.slice_to(idx+1).clone_iter()); + v.push_all(extension.clone_iter()); } else { let extension = extension.container_as_bytes(); v = vec::with_capacity(idx + extension.len() + 1); - v.push_all(name.slice_to(idx+1)); - v.push_all(extension); + v.push_all(name.slice_to(idx+1).clone_iter()); + v.push_all(extension.clone_iter()); } Some(v) } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 3f2535765dd4a..4a48383671773 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -10,7 +10,7 @@ //! POSIX file path handling -use container::Container; +use container::{Container, MutableSeq}; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::Eq; @@ -22,6 +22,7 @@ use str::Str; use to_bytes::IterBytes; use vec; use vec::{CopyableVector, RSplitIterator, SplitIterator, Vector, VectorVector}; +use vec::{OwnedVector, ImmutableCopyableVector}; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; /// Iterator that yields successive components of a Path as &[u8] @@ -123,9 +124,9 @@ impl GenericPathUnsafe for Path { match self.sepidx { None if bytes!("..") == self.repr => { let mut v = vec::with_capacity(3 + filename.len()); - v.push_all(dot_dot_static); + v.push_all(dot_dot_static.clone_iter()); v.push(sep_byte); - v.push_all(filename); + v.push_all(filename.clone_iter()); self.repr = Path::normalize(v); } None => { @@ -133,15 +134,15 @@ impl GenericPathUnsafe for Path { } Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => { let mut v = vec::with_capacity(self.repr.len() + 1 + filename.len()); - v.push_all(self.repr); + v.push_all(self.repr.clone_iter()); v.push(sep_byte); - v.push_all(filename); + v.push_all(filename.clone_iter()); self.repr = Path::normalize(v); } Some(idx) => { let mut v = vec::with_capacity(idx + 1 + filename.len()); - v.push_all(self.repr.slice_to(idx+1)); - v.push_all(filename); + v.push_all(self.repr.slice_to(idx+1).clone_iter()); + v.push_all(filename.clone_iter()); self.repr = Path::normalize(v); } } @@ -155,9 +156,9 @@ impl GenericPathUnsafe for Path { self.repr = Path::normalize(path); } else { let mut v = vec::with_capacity(self.repr.len() + path.len() + 1); - v.push_all(self.repr); + v.push_all(self.repr.clone_iter()); v.push(sep_byte); - v.push_all(path); + v.push_all(path.clone_iter()); self.repr = Path::normalize(v); } self.sepidx = self.repr.rposition_elem(&sep_byte); @@ -345,12 +346,12 @@ impl Path { if !is_abs { match it.next() { None => (), - Some(comp) => v.push_all(comp) + Some(comp) => v.push_all(comp.clone_iter()) } } for comp in it { v.push(sep_byte); - v.push_all(comp); + v.push_all(comp.clone_iter()); } Some(v) } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 114f675cdba91..ccc9e53187982 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -14,6 +14,7 @@ use ascii::AsciiCast; use c_str::{CString, ToCStr}; use cast; use cmp::Eq; +use container::MutableSeq; use from_str::FromStr; use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Invert, Iterator, Map}; use option::{Option, Some, None}; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 83439d4c90305..94b89ad86d5d0 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -51,7 +51,8 @@ pub use c_str::ToCStr; pub use char::Char; pub use clone::{Clone, DeepClone}; pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv}; -pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; +pub use container::{Container, NewContainer, Mutable, Seq, MutableSeq, Map, MutableMap}; +pub use container::{Set, MutableSet}; pub use default::Default; pub use from_str::FromStr; pub use hash::Hash; diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index 2f9478716a37b..23920bd828548 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -18,7 +18,7 @@ More runtime type reflection use cast::transmute; use char; -use container::Container; +use container::{Container, MutableSeq}; use io; use iter::Iterator; use libc::c_void; @@ -28,7 +28,6 @@ use reflect; use reflect::{MovePtr, align}; use str::StrSlice; use to_str::ToStr; -use vec::OwnedVector; use unstable::intrinsics::{Disr, Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc}; use unstable::raw; diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 690b4e06d4999..3f00471a23e91 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -12,13 +12,13 @@ use clone::Clone; use cmp::Eq; +use container::MutableSeq; use fmt; use iter::Iterator; use option::{None, Option, Some}; use option::{ToOption, IntoOption, AsOption}; use str::OwnedStr; use to_str::ToStr; -use vec::OwnedVector; use vec; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). diff --git a/src/libstd/rt/message_queue.rs b/src/libstd/rt/message_queue.rs index 10e457368f007..519b1834e8259 100644 --- a/src/libstd/rt/message_queue.rs +++ b/src/libstd/rt/message_queue.rs @@ -12,7 +12,6 @@ //! single consumer. use kinds::Send; -use vec::OwnedVector; use option::Option; use clone::Clone; use rt::mpsc_queue::Queue; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index ce8d1ab1983a1..bf2a2a68d4315 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -58,7 +58,7 @@ Several modules in `core` are clients of `rt`: #[allow(missing_doc)]; use clone::Clone; -use container::Container; +use container::{Container, MutableSeq}; use iter::Iterator; use option::{Option, None, Some}; use ptr::RawPtr; diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index fa17efc833bd0..096acdf434d43 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -27,8 +27,6 @@ use borrow::{to_uint}; use rand::{XorShiftRng, Rng, Rand}; use iter::range; use unstable::mutex::Mutex; -use vec::{OwnedVector}; - /// A scheduler is responsible for coordinating the execution of Tasks /// on a single thread. The scheduler runs inside a slightly modified diff --git a/src/libstd/rt/tube.rs b/src/libstd/rt/tube.rs index 5e867bcdfbac6..b09d3b61eb2c7 100644 --- a/src/libstd/rt/tube.rs +++ b/src/libstd/rt/tube.rs @@ -19,7 +19,6 @@ use super::rc::RC; use rt::sched::Scheduler; use rt::kill::BlockedTask; use rt::local::Local; -use vec::OwnedVector; use container::Container; struct TubeState { diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 14d49df59a4c6..604a901328dc5 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -331,6 +331,7 @@ pub fn process_output(prog: &str, args: &[~str]) -> Option { #[cfg(test)] mod tests { + use container::MutableSeq; use libc::c_int; use option::{Option, None, Some}; use os; @@ -433,7 +434,7 @@ mod tests { let mut buf = [0, ..1024]; loop { match reader.read(buf) { - Some(n) => { res.push_all(buf.slice_to(n)); } + Some(n) => { res.push_all(buf.slice_to(n).clone_iter()); } None => break } } diff --git a/src/libstd/select.rs b/src/libstd/select.rs index cca64244db569..8c576232b48bb 100644 --- a/src/libstd/select.rs +++ b/src/libstd/select.rs @@ -134,6 +134,7 @@ pub fn select2, TB, B: SelectPort>(mut a: A, mut b: B) #[cfg(test)] mod test { use super::*; + use container::MutableSeq; use clone::Clone; use num::Times; use option::*; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index f131076513058..5641999c45802 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -95,7 +95,7 @@ use cast::transmute; use char; use char::Char; use clone::{Clone, DeepClone}; -use container::{Container, Mutable}; +use container::{Container, NewContainer, Mutable, MutableSeq}; use iter::{Iterator, FromIterator, Extendable, range}; use iter::{Filter, AdditiveIterator, Map}; use iter::{Invert, DoubleEndedIterator, ExactSize}; @@ -108,7 +108,7 @@ use to_str::ToStr; use from_str::FromStr; use uint; use vec; -use vec::{OwnedVector, OwnedCopyableVector, ImmutableVector, MutableVector}; +use vec::{OwnedVector, ImmutableVector, MutableVector}; use default::Default; use send_str::{SendStr, SendStrOwned}; @@ -1323,6 +1323,28 @@ impl Container for @str { fn len(&self) -> uint { self.as_slice().len() } } +impl NewContainer for ~str { + #[inline] + fn new() -> ~str { ~"" } + + #[inline] + fn with_capacity(capacity: uint) -> ~str { + with_capacity(capacity) + } +} + +impl NewContainer for @str { + #[inline] + fn new() -> @str { @"" } + + #[inline] + fn with_capacity(capacity: uint) -> @str { + unsafe { + cast::transmute(at_vec::with_capacity::<@[u8]>(capacity)) + } + } +} + impl Mutable for ~str { /// Remove all content, make the string empty #[inline] @@ -2298,8 +2320,10 @@ impl<'a> StrSlice<'a> for &'a str { } fn to_utf16(&self) -> ~[u16] { - let mut u = ~[]; - for ch in self.chars() { + let mut iter = self.chars(); + let (len, _) = iter.size_hint(); + let mut u = vec::with_capacity(len); + for ch in iter { // Arithmetic with u32 literals is easier on the eyes than chars. let mut ch = ch as u32; @@ -2313,8 +2337,9 @@ impl<'a> StrSlice<'a> for &'a str { assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32); ch -= 0x1_0000_u32; let w1 = 0xD800_u16 | ((ch >> 10) as u16); + u.push(w1); let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all([w1, w2]) + u.push(w2); } } u diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs index 09dd091d0e716..313947b5080d1 100644 --- a/src/libstd/trie.rs +++ b/src/libstd/trie.rs @@ -38,6 +38,11 @@ impl Container for TrieMap { fn len(&self) -> uint { self.length } } +impl NewContainer for TrieMap { + #[inline] + fn with_capacity(_capacity: uint) -> TrieMap { TrieMap::new() } +} + impl Mutable for TrieMap { /// Clear the map, removing all values. #[inline] @@ -237,32 +242,46 @@ impl Mutable for TrieSet { fn clear(&mut self) { self.map.clear() } } -impl TrieSet { - /// Create an empty TrieSet +impl Set for TrieSet { #[inline] - pub fn new() -> TrieSet { - TrieSet{map: TrieMap::new()} + fn contains(&self, value: &uint) -> bool { + self.map.contains_key(value) } - /// Return true if the set contains a value #[inline] - pub fn contains(&self, value: &uint) -> bool { - self.map.contains_key(value) + fn is_disjoint(&self, other: &TrieSet) -> bool { + self.iter().all(|v| !other.contains(&v)) + } + + #[inline] + fn is_subset(&self, other: &TrieSet) -> bool { + self.iter().all(|v| other.contains(&v)) } - /// Add a value to the set. Return true if the value was not already - /// present in the set. #[inline] - pub fn insert(&mut self, value: uint) -> bool { + fn is_superset(&self, other: &TrieSet) -> bool { + other.is_subset(self) + } +} + +impl MutableSet for TrieSet { + #[inline] + fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) } - /// Remove a value from the set. Return true if the value was - /// present in the set. #[inline] - pub fn remove(&mut self, value: &uint) -> bool { + fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) } +} + +impl TrieSet { + /// Create an empty TrieSet + #[inline] + pub fn new() -> TrieSet { + TrieSet{map: TrieMap::new()} + } /// Visit all values in order #[inline] diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index be9adc91e0311..c8054e2ce11a3 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -103,7 +103,7 @@ There are a number of free functions that create or take vectors, for example: use cast; use clone::{Clone, DeepClone}; -use container::{Container, Mutable}; +use container::{Container, Mutable, NewContainer, Seq, MutableSeq}; use cmp::{Eq, TotalOrd, Ordering, Less, Equal, Greater}; use cmp; use default::Default; @@ -158,7 +158,7 @@ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { // FIXME (#7136): manually inline from_fn for 2x plus speedup (sadly very // important, from_elem is a bottleneck in borrowck!). Unfortunately it // still is substantially slower than using the unsafe - // vec::with_capacity/ptr::set_memory for primitive types. + // container::with_capacity/ptr::set_memory for primitive types. unsafe { let mut v = with_capacity(n_elts); let p = v.as_mut_ptr(); @@ -316,9 +316,9 @@ impl<'a, T> Iterator<&'a [T]> for RSplitIterator<'a, T> { /// Iterates over the `rhs` vector, copying each element and appending it to the /// `lhs`. Afterwards, the `lhs` is then returned for use again. #[inline] -pub fn append(lhs: ~[T], rhs: &[T]) -> ~[T] { +pub fn append(lhs: ~[T], rhs: &[T]) -> ~[T] { let mut v = lhs; - v.push_all(rhs); + v.push_all(rhs.clone_iter()); v } @@ -359,7 +359,7 @@ impl<'a, T: Clone, V: Vector> VectorVector for &'a [V] { let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len()); let mut result = with_capacity(size); for v in self.iter() { - result.push_all(v.as_slice()) + result.push_all(v.as_slice().clone_iter()); } result } @@ -370,7 +370,7 @@ impl<'a, T: Clone, V: Vector> VectorVector for &'a [V] { let mut first = true; for v in self.iter() { if first { first = false } else { result.push(sep.clone()) } - result.push_all(v.as_slice()) + result.push_all(v.as_slice().clone_iter()); } result } @@ -732,8 +732,8 @@ pub mod traits { #[inline] fn add(&self, rhs: &V) -> ~[T] { let mut res = with_capacity(self.len() + rhs.as_slice().len()); - res.push_all(*self); - res.push_all(rhs.as_slice()); + res.push_all(self.clone_iter()); + res.push_all(rhs.as_slice().clone_iter()); res } } @@ -786,6 +786,158 @@ impl Container for ~[T] { } } +impl Seq for ~[T] { } + +impl MutableSeq for ~[T] { + #[inline] + fn push(&mut self, t: T) { + unsafe { + if owns_managed::() { + let repr: **Box> = cast::transmute(&mut *self); + let fill = (**repr).data.fill; + if (**repr).data.alloc <= fill { + self.reserve_additional(1); + } + + push_fast(self, t); + } else { + let repr: **Vec<()> = cast::transmute(&mut *self); + let fill = (**repr).fill; + if (**repr).alloc <= fill { + self.reserve_additional(1); + } + + push_fast(self, t); + } + } + + // This doesn't bother to make sure we have space. + #[inline] // really pretty please + unsafe fn push_fast(this: &mut ~[T], t: T) { + if owns_managed::() { + let repr: **mut Box> = cast::transmute(this); + let fill = (**repr).data.fill; + (**repr).data.fill += mem::nonzero_size_of::(); + let p = to_unsafe_ptr(&((**repr).data.data)); + let p = ptr::offset(p, fill as int) as *mut T; + intrinsics::move_val_init(&mut(*p), t); + } else { + let repr: **mut Vec = cast::transmute(this); + let fill = (**repr).fill; + (**repr).fill += mem::nonzero_size_of::(); + let p = to_unsafe_ptr(&((**repr).data)); + let p = ptr::offset(p, fill as int) as *mut T; + intrinsics::move_val_init(&mut(*p), t); + } + } + } + + #[inline] + fn push_all>(&mut self, mut iter: Iter) { + let (len, _) = iter.size_hint(); + self.reserve_additional(len); + + for x in iter { + self.push(x); + } + } + + fn pop_opt(&mut self) -> Option { + match self.len() { + 0 => None, + ln => { + let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]); + unsafe { + self.set_len(ln - 1u); + Some(ptr::read_ptr(&*valptr)) + } + } + } + } + + fn shift_opt(&mut self) -> Option { + unsafe { + let ln = match self.len() { + 0 => return None, + 1 => return self.pop_opt(), + 2 => { + let last = self.pop(); + let first = self.pop_opt(); + self.push(last); + return first; + } + x => x + }; + + let next_ln = self.len() - 1; + + // Save the last element. We're going to overwrite its position + let work_elt = self.pop(); + // We still should have room to work where what last element was + assert!(self.capacity() >= ln); + // Pretend like we have the original length so we can use + // the vector copy_memory to overwrite the hole we just made + self.set_len(ln); + + // Memcopy the head element (the one we want) to the location we just + // popped. For the moment it unsafely exists at both the head and last + // positions + { + let first_slice = self.slice(0, 1); + let last_slice = self.slice(next_ln, ln); + raw::copy_memory(cast::transmute(last_slice), first_slice); + } + + // Memcopy everything to the left one element + { + let init_slice = self.slice(0, next_ln); + let tail_slice = self.slice(1, ln); + raw::copy_memory(cast::transmute(init_slice), + tail_slice); + } + + // Set the new length. Now the vector is back to normal + self.set_len(next_ln); + + // Swap out the element we want from the end + let vp = self.as_mut_ptr(); + let vp = ptr::mut_offset(vp, (next_ln - 1) as int); + + Some(ptr::replace_ptr(vp, work_elt)) + } + } + + + fn unshift(&mut self, x: T) { + let v = util::replace(self, ~[x]); + self.push_all_move(v); + } + + fn insert(&mut self, i: uint, x:T) { + let len = self.len(); + assert!(i <= len); + + self.push(x); + let mut j = len; + while j > i { + self.swap(j, j - 1); + j -= 1; + } + } + + fn remove(&mut self, i: uint) -> T { + let len = self.len(); + assert!(i < len); + + let mut j = i; + while j < len - 1 { + self.swap(j, j + 1); + j += 1; + } + self.pop() + } +} + /// Extension methods for vector slices with copyable elements pub trait CopyableVector { /// Copy `self` into a new owned vector @@ -829,6 +981,14 @@ impl CopyableVector for @[T] { fn into_owned(self) -> ~[T] { self.to_owned() } } +impl NewContainer for ~[T] { + #[inline] + fn new() -> ~[T] { ~[] } + + #[inline] + fn with_capacity(capacity: uint) -> ~[T] { with_capacity(capacity) } +} + /// Extension methods for vectors pub trait ImmutableVector<'a, T> { /** @@ -1281,19 +1441,20 @@ impl<'a, T: TotalOrd> ImmutableTotalOrdVector for &'a [T] { } /// Extension methods for vectors containing `Clone` elements. -pub trait ImmutableCopyableVector { - /** - * Partitions the vector into those that satisfies the predicate, and - * those that do not. - */ +pub trait ImmutableCopyableVector<'a, T> { + /// Partitions the vector into those that satisfies the predicate, and + /// those that do not. fn partitioned(&self, f: |&T| -> bool) -> (~[T], ~[T]); /// Create an iterator that yields every possible permutation of the /// vector in succession. fn permutations(self) -> Permutations; + + /// Returns an iterator that clones the value. + fn clone_iter(self) -> CloneIterator<'a, T>; } -impl<'a,T:Clone> ImmutableCopyableVector for &'a [T] { +impl<'a, T: Clone> ImmutableCopyableVector<'a, T> for &'a [T] { #[inline] fn partitioned(&self, f: |&T| -> bool) -> (~[T], ~[T]) { let mut lefts = ~[]; @@ -1317,6 +1478,28 @@ impl<'a,T:Clone> ImmutableCopyableVector for &'a [T] { } } + #[inline] + fn clone_iter(self) -> CloneIterator<'a, T> { + CloneIterator { + iter: self.iter(), + } + } +} + +/// An iterator for iterating over a vector. +pub struct CloneIterator<'a, T> { + priv iter: VecIterator<'a, T>, + +} + +impl<'a, T: Clone> Iterator for CloneIterator<'a, T> { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + Some(value) => Some(value.clone()), + None => None, + } + } } /// Extension methods for owned vectors. @@ -1389,8 +1572,6 @@ pub trait OwnedVector { /// Shrink the capacity of the vector to match the length fn shrink_to_fit(&mut self); - /// Append an element to a vector - fn push(&mut self, t: T); /// Takes ownership of the vector `rhs`, moving all elements into /// the current vector. This does not copy any elements, and it is /// illegal to use the `rhs` vector after calling this method @@ -1404,67 +1585,40 @@ pub trait OwnedVector { /// assert!(a == ~[~1, ~2, ~3, ~4]); /// ``` fn push_all_move(&mut self, rhs: ~[T]); - /// Remove the last element from a vector and return it, failing if it is empty - fn pop(&mut self) -> T; - /// Remove the last element from a vector and return it, or `None` if it is empty - fn pop_opt(&mut self) -> Option; - /// Removes the first element from a vector and return it - fn shift(&mut self) -> T; - /// Removes the first element from a vector and return it, or `None` if it is empty - fn shift_opt(&mut self) -> Option; - /// Prepend an element to the vector - fn unshift(&mut self, x: T); - - /// Insert an element at position i within v, shifting all - /// elements after position i one position to the right. - fn insert(&mut self, i: uint, x:T); - - /// Remove and return the element at position i within v, shifting - /// all elements after position i one position to the left. - fn remove(&mut self, i: uint) -> T; - /** - * Remove an element from anywhere in the vector and return it, replacing it - * with the last element. This does not preserve ordering, but is O(1). - * - * Fails if index >= length. - */ + /// Remove an element from anywhere in the vector and return it, replacing it + /// with the last element. This does not preserve ordering, but is O(1). + /// + /// Fails if index >= length. fn swap_remove(&mut self, index: uint) -> T; /// Shorten a vector, dropping excess elements. fn truncate(&mut self, newlen: uint); - /** - * Like `filter()`, but in place. Preserves order of `v`. Linear time. - */ + /// Like `filter()`, but in place. Preserves order of `v`. Linear time. fn retain(&mut self, f: |t: &T| -> bool); - /** - * Partitions the vector into those that satisfies the predicate, and - * those that do not. - */ + + /// Partitions the vector into those that satisfies the predicate, and + /// those that do not. fn partition(self, f: |&T| -> bool) -> (~[T], ~[T]); - /** - * Expands a vector in place, initializing the new elements to the result of - * a function. - * - * Function `init_op` is called `n` times with the values [0..`n`) - * - * # Arguments - * - * * n - The number of elements to add - * * init_op - A function to call to retrieve each appended element's - * value - */ + /// Expands a vector in place, initializing the new elements to the result of + /// a function. + /// + /// Function `init_op` is called `n` times with the values [0..`n`) + /// + /// # Arguments + /// + /// * n - The number of elements to add + /// * init_op - A function to call to retrieve each appended element's + /// value fn grow_fn(&mut self, n: uint, op: |uint| -> T); - /** - * Sets the length of a vector - * - * This will explicitly set the size of the vector, without actually - * modifying its buffers, so it is up to the caller to ensure that - * the vector is actually the specified size. - */ + /// Sets the length of a vector + /// + /// This will explicitly set the size of the vector, without actually + /// modifying its buffers, so it is up to the caller to ensure that + /// the vector is actually the specified size. unsafe fn set_len(&mut self, new_len: uint); } @@ -1537,50 +1691,6 @@ impl OwnedVector for ~[T] { } } - #[inline] - fn push(&mut self, t: T) { - unsafe { - if owns_managed::() { - let repr: **Box> = cast::transmute(&mut *self); - let fill = (**repr).data.fill; - if (**repr).data.alloc <= fill { - self.reserve_additional(1); - } - - push_fast(self, t); - } else { - let repr: **Vec<()> = cast::transmute(&mut *self); - let fill = (**repr).fill; - if (**repr).alloc <= fill { - self.reserve_additional(1); - } - - push_fast(self, t); - } - } - - // This doesn't bother to make sure we have space. - #[inline] // really pretty please - unsafe fn push_fast(this: &mut ~[T], t: T) { - if owns_managed::() { - let repr: **mut Box> = cast::transmute(this); - let fill = (**repr).data.fill; - (**repr).data.fill += mem::nonzero_size_of::(); - let p = to_unsafe_ptr(&((**repr).data.data)); - let p = ptr::offset(p, fill as int) as *mut T; - intrinsics::move_val_init(&mut(*p), t); - } else { - let repr: **mut Vec = cast::transmute(this); - let fill = (**repr).fill; - (**repr).fill += mem::nonzero_size_of::(); - let p = to_unsafe_ptr(&((**repr).data)); - let p = ptr::offset(p, fill as int) as *mut T; - intrinsics::move_val_init(&mut(*p), t); - } - } - - } - #[inline] fn push_all_move(&mut self, mut rhs: ~[T]) { let self_len = self.len(); @@ -1596,108 +1706,6 @@ impl OwnedVector for ~[T] { } } - fn pop_opt(&mut self) -> Option { - match self.len() { - 0 => None, - ln => { - let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]); - unsafe { - self.set_len(ln - 1u); - Some(ptr::read_ptr(&*valptr)) - } - } - } - } - - - #[inline] - fn pop(&mut self) -> T { - self.pop_opt().expect("pop: empty vector") - } - - #[inline] - fn shift(&mut self) -> T { - self.shift_opt().expect("shift: empty vector") - } - - fn shift_opt(&mut self) -> Option { - unsafe { - let ln = match self.len() { - 0 => return None, - 1 => return self.pop_opt(), - 2 => { - let last = self.pop(); - let first = self.pop_opt(); - self.push(last); - return first; - } - x => x - }; - - let next_ln = self.len() - 1; - - // Save the last element. We're going to overwrite its position - let work_elt = self.pop(); - // We still should have room to work where what last element was - assert!(self.capacity() >= ln); - // Pretend like we have the original length so we can use - // the vector copy_memory to overwrite the hole we just made - self.set_len(ln); - - // Memcopy the head element (the one we want) to the location we just - // popped. For the moment it unsafely exists at both the head and last - // positions - { - let first_slice = self.slice(0, 1); - let last_slice = self.slice(next_ln, ln); - raw::copy_memory(cast::transmute(last_slice), first_slice); - } - - // Memcopy everything to the left one element - { - let init_slice = self.slice(0, next_ln); - let tail_slice = self.slice(1, ln); - raw::copy_memory(cast::transmute(init_slice), - tail_slice); - } - - // Set the new length. Now the vector is back to normal - self.set_len(next_ln); - - // Swap out the element we want from the end - let vp = self.as_mut_ptr(); - let vp = ptr::mut_offset(vp, (next_ln - 1) as int); - - Some(ptr::replace_ptr(vp, work_elt)) - } - } - - fn unshift(&mut self, x: T) { - let v = util::replace(self, ~[x]); - self.push_all_move(v); - } - fn insert(&mut self, i: uint, x:T) { - let len = self.len(); - assert!(i <= len); - - self.push(x); - let mut j = len; - while j > i { - self.swap(j, j - 1); - j -= 1; - } - } - fn remove(&mut self, i: uint) -> T { - let len = self.len(); - assert!(i < len); - - let mut j = i; - while j < len - 1 { - self.swap(j, j + 1); - j += 1; - } - self.pop() - } fn swap_remove(&mut self, index: uint) -> T { let ln = self.len(); if index >= ln { @@ -1781,18 +1789,6 @@ impl Mutable for ~[T] { /// Extension methods for owned vectors containing `Clone` elements. pub trait OwnedCopyableVector { - /// Iterates over the slice `rhs`, copies each element, and then appends it to - /// the vector provided `v`. The `rhs` vector is traversed in-order. - /// - /// # Example - /// - /// ```rust - /// let mut a = ~[1]; - /// a.push_all([2, 3, 4]); - /// assert!(a == ~[1, 2, 3, 4]); - /// ``` - fn push_all(&mut self, rhs: &[T]); - /** * Expands a vector in place, initializing the new elements to a given value * @@ -1815,15 +1811,6 @@ pub trait OwnedCopyableVector { } impl OwnedCopyableVector for ~[T] { - #[inline] - fn push_all(&mut self, rhs: &[T]) { - let new_len = self.len() + rhs.len(); - self.reserve(new_len); - - for elt in rhs.iter() { - self.push((*elt).clone()) - } - } fn grow(&mut self, n: uint, initval: &T) { let new_len = self.len() + n; self.reserve_at_least(new_len); @@ -4231,6 +4218,33 @@ mod bench { }) } + #[bench] + fn push_all_clone_iter(bh: &mut BenchHarness) { + bh.iter(|| { + let mut vec: ~[uint] = ~[0u]; + let v = vec::from_elem(100, 0); + vec.push_all(v.clone_iter()); + }) + } + + #[bench] + fn push_all_move_iter(bh: &mut BenchHarness) { + bh.iter(|| { + let mut vec: ~[uint] = ~[0u]; + let v = vec::from_elem(100, 0); + vec.push_all(v.move_iter()); + }) + } + + #[bench] + fn push_all_move(bh: &mut BenchHarness) { + bh.iter(|| { + let mut vec: ~[uint] = ~[0u]; + let v = vec::from_elem(100, 0); + vec.push_all_move(v); + }) + } + #[bench] fn starts_with_same_vector(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index ac5254f1abafc..ce9f4a7f7bfc7 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -229,7 +229,7 @@ pub fn find_linkage_metas(attrs: &[Attribute]) -> ~[@MetaItem] { let mut result = ~[]; for attr in attrs.iter().filter(|at| "link" == at.name()) { match attr.meta().node { - MetaList(_, ref items) => result.push_all(*items), + MetaList(_, ref items) => result.push_all(items.clone_iter()), _ => () } } diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index 247962e0b9424..050a3c8c0e0c7 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -117,7 +117,7 @@ impl OptVec { let mut v0 = ~[t]; match *self { Empty => {} - Vec(ref v1) => { v0.push_all(*v1); } + Vec(ref v1) => { v0.push_all(v1.clone_iter()); } } return Vec(v0); } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 33e3bae99a758..92c369fe81eae 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3382,7 +3382,7 @@ impl Parser { while (*self.token != token::RBRACE) { // parsing items even when they're not allowed lets us give // better error messages and recover more gracefully. - attributes_box.push_all(self.parse_outer_attributes()); + attributes_box.push_all(self.parse_outer_attributes().move_iter()); match *self.token { token::SEMI => { if !attributes_box.is_empty() { diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index 9be462f736bc5..eb6e27ddb90a0 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -122,11 +122,11 @@ fn vec_push_all() { for i in range(0u, 1500) { let mut rv = vec::from_elem(r.gen_range(0u, i + 1), i); if r.gen() { - v.push_all(rv); + v.push_all(rv.clone_iter()); } else { util::swap(&mut v, &mut rv); - v.push_all(rv); + v.push_all(rv.clone_iter()); } } } @@ -145,7 +145,7 @@ fn is_utf8_multibyte() { let s = "b¢€𤭢"; let mut v : ~[u8]= ~[]; for _ in range(0u, 5000) { - v.push_all(s.as_bytes()); + v.push_all(s.as_bytes().clone_iter()); if !str::is_utf8(v) { fail!("is_utf8 failed"); }