Skip to content

Commit

Permalink
auto merge of #17920 : thestinger/rust/vec, r=aturon
Browse files Browse the repository at this point in the history
Introduce conversions between `Box<[T]>` and `Vec<T>` and use it to reimplement the `vec![]` macro for efficiency.
  • Loading branch information
bors committed Oct 10, 2014
2 parents 78a7676 + 02d976a commit 1add4de
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 15 deletions.
25 changes: 25 additions & 0 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@

#![doc(primitive = "slice")]

use alloc::boxed::Box;
use core::cmp;
use core::mem::size_of;
use core::mem;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)]
Expand Down
25 changes: 23 additions & 2 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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"]
Expand Down Expand Up @@ -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;
}
Expand All @@ -1758,7 +1773,6 @@ impl<T> MutableSeq<T> for Vec<T> {
}
}
}

}

/// An iterator that moves out of a vector.
Expand Down Expand Up @@ -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(|| {
Expand Down
1 change: 0 additions & 1 deletion src/libstd/io/net/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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![]
}
16 changes: 7 additions & 9 deletions src/libstd/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 1add4de

Please sign in to comment.