diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index e07f6dbd35d..955a1a5068b 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -87,6 +87,7 @@ #![doc(primitive = "slice")] +use alloc::boxed::Box; use core::cmp; use core::mem::size_of; use core::mem; @@ -298,6 +299,23 @@ impl<'a, T: Clone> CloneableVector for &'a [T] { fn into_vec(self) -> Vec { self.to_vec() } } +#[experimental] +pub trait BoxedSlice { + /// Convert `self` into a vector without clones or allocation. + fn into_vec(self) -> Vec; +} + +impl BoxedSlice for Box<[T]> { + #[experimental] + fn into_vec(mut self) -> Vec { + unsafe { + let xs = Vec::from_raw_parts(self.len(), self.len(), self.as_mut_ptr()); + mem::forget(self); + xs + } + } +} + /// Extension methods for vectors containing `Clone` elements. pub trait ImmutableCloneableVector { /// Partitions the vector into two vectors `(a, b)`, where all @@ -2308,6 +2326,13 @@ mod tests { let y: &mut [int] = []; assert!(y.last_mut().is_none()); } + + #[test] + fn test_into_vec() { + let xs = box [1u, 2, 3]; + let ys = xs.into_vec(); + assert_eq!(ys.as_slice(), [1u, 2, 3].as_slice()); + } } #[cfg(test)] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 894ca3d7f2e..a82856c013d 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -14,6 +14,7 @@ use core::prelude::*; +use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::cmp::max; use core::default::Default; @@ -757,6 +758,20 @@ impl Vec { } } + /// Convert the vector into Box<[T]>. + /// + /// Note that this will drop any excess capacity. Calling this and converting back to a vector + /// with `into_vec()` is equivalent to calling `shrink_to_fit()`. + #[experimental] + pub fn into_boxed_slice(mut self) -> Box<[T]> { + self.shrink_to_fit(); + unsafe { + let xs: Box<[T]> = mem::transmute(self.as_mut_slice()); + mem::forget(self); + xs + } + } + /// Deprecated, call `push` instead #[inline] #[deprecated = "call .push() instead"] @@ -1734,7 +1749,7 @@ impl MutableSeq for Vec { let size = max(old_size, 2 * mem::size_of::()) * 2; if old_size > size { fail!("capacity overflow") } unsafe { - self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::(), size); + self.ptr = alloc_or_realloc(self.ptr, old_size, size); } self.cap = max(self.cap, 2) * 2; } @@ -1758,7 +1773,6 @@ impl MutableSeq for Vec { } } } - } /// An iterator that moves out of a vector. @@ -2632,6 +2646,13 @@ mod tests { assert!(vec2 == vec!((), (), ())); } + #[test] + fn test_into_boxed_slice() { + let xs = vec![1u, 2, 3]; + let ys = xs.into_boxed_slice(); + assert_eq!(ys.as_slice(), [1u, 2, 3].as_slice()); + } + #[bench] fn bench_new(b: &mut Bencher) { b.iter(|| { diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index cbd02abff7d..e2a850c58e4 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -18,7 +18,6 @@ //! listener (socket server) implements the `Listener` and `Acceptor` traits. use clone::Clone; -use collections::MutableSeq; use io::IoResult; use iter::Iterator; use slice::ImmutableSlice; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ca11a7c04b7..13adfeecf85 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -272,7 +272,9 @@ mod std { // The test runner calls ::std::os::args() but really wants realstd #[cfg(test)] pub use realstd::os as os; // The test runner requires std::slice::Vector, so re-export std::slice just for it. - #[cfg(test)] pub use slice; + // + // It is also used in vec![] + pub use slice; - pub use collections; // vec!() uses MutableSeq + pub use boxed; // used for vec![] } diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index fa356432a67..1ad3d6eed94 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -323,16 +323,14 @@ macro_rules! try( /// Create a `std::vec::Vec` containing the arguments. #[macro_export] -macro_rules! vec( - ($($e:expr),*) => ({ - // leading _ to allow empty construction without a warning. - let mut _temp = ::std::vec::Vec::new(); - $(_temp.push($e);)* - _temp +macro_rules! vec[ + ($($x:expr),*) => ({ + use std::slice::BoxedSlice; + let xs: ::std::boxed::Box<[_]> = box [$($x),*]; + xs.into_vec() }); - ($($e:expr),+,) => (vec!($($e),+)) -) - + ($($x:expr,)*) => (vec![$($x),*]) +] /// A macro to select an event from a number of receivers. /// diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index abfb2de13c5..db9f3114cda 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -88,7 +88,7 @@ #[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice}; #[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice}; #[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice}; -#[doc(no_inline)] pub use slice::{AsSlice, VectorVector}; +#[doc(no_inline)] pub use slice::{AsSlice, VectorVector, BoxedSlice}; #[doc(no_inline)] pub use slice::MutableSliceAllocating; #[doc(no_inline)] pub use string::String; #[doc(no_inline)] pub use vec::Vec;