auto merge of #17920 : thestinger/rust/vec, r=aturon

Introduce conversions between `Box<[T]>` and `Vec<T>` and use it to reimplement the `vec![]` macro for efficiency.
This commit is contained in:
bors 2014-10-10 18:47:03 +00:00
commit 1add4dedc1
6 changed files with 60 additions and 15 deletions

View File

@ -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<T> for &'a [T] {
fn into_vec(self) -> Vec<T> { self.to_vec() }
}
#[experimental]
pub trait BoxedSlice<T> {
/// Convert `self` into a vector without clones or allocation.
fn into_vec(self) -> Vec<T>;
}
impl<T> BoxedSlice<T> for Box<[T]> {
#[experimental]
fn into_vec(mut self) -> Vec<T> {
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<T> {
/// 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)]

View File

@ -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<T> Vec<T> {
}
}
/// 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<T> MutableSeq<T> for Vec<T> {
let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
if old_size > size { fail!("capacity overflow") }
unsafe {
self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::<T>(), size);
self.ptr = alloc_or_realloc(self.ptr, old_size, size);
}
self.cap = max(self.cap, 2) * 2;
}
@ -1758,7 +1773,6 @@ impl<T> MutableSeq<T> for Vec<T> {
}
}
}
}
/// 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(|| {

View File

@ -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;

View File

@ -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![]
}

View File

@ -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.
///

View File

@ -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;