Skip to content

Commit 300d865

Browse files
committed
Add a mechanism to convert from Vec<T> to ~[T]
Add a new trait FromVec with one self-less method from_vec(). This is kind of like FromIterator, but it consumes a Vec<T>. It's only implemented for ~[T], but the idea is post-DST it can be implemented for any Boxed<[T]>.
1 parent dbbb847 commit 300d865

File tree

1 file changed

+73
-1
lines changed

1 file changed

+73
-1
lines changed

src/libstd/vec.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use ptr::RawPtr;
2828
use ptr;
2929
use rt::global_heap::{malloc_raw, realloc_raw};
3030
use raw::Slice;
31+
use RawVec = raw::Vec;
3132
use slice::{ImmutableEqVector, ImmutableVector, Items, MutItems, MutableVector};
3233
use slice::{MutableTotalOrdVector, OwnedVector, Vector};
3334
use slice::{MutableVectorAllocating};
@@ -1465,6 +1466,50 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
14651466
(ts, us)
14661467
}
14671468

1469+
/// Mechanism to convert from a `Vec<T>` to a `[T]`.
1470+
///
1471+
/// In a post-DST world this will be used to convert to any `Ptr<[T]>`.
1472+
///
1473+
/// This could be implemented on more types than just pointers to vectors, but
1474+
/// the recommended approach for those types is to implement `FromIterator`.
1475+
// FIXME(#12938): Update doc comment when DST lands
1476+
pub trait FromVec<T> {
1477+
/// Convert a `Vec<T>` into the receiver type.
1478+
fn from_vec(v: Vec<T>) -> Self;
1479+
}
1480+
1481+
impl<T> FromVec<T> for ~[T] {
1482+
fn from_vec(mut v: Vec<T>) -> ~[T] {
1483+
let len = v.len();
1484+
let data_size = len.checked_mul(&mem::size_of::<T>());
1485+
let data_size = data_size.expect("overflow in from_vec()");
1486+
let size = mem::size_of::<RawVec<()>>().checked_add(&data_size);
1487+
let size = size.expect("overflow in from_vec()");
1488+
1489+
// In a post-DST world, we can attempt to reuse the Vec allocation by calling
1490+
// shrink_to_fit() on it. That may involve a reallocation+memcpy, but that's no
1491+
// diffrent than what we're doing manually here.
1492+
1493+
let vp = v.as_mut_ptr();
1494+
1495+
unsafe {
1496+
let ret = malloc_raw(size) as *mut RawVec<()>;
1497+
1498+
(*ret).fill = len * mem::nonzero_size_of::<T>();
1499+
(*ret).alloc = len * mem::nonzero_size_of::<T>();
1500+
1501+
ptr::copy_nonoverlapping_memory(&mut (*ret).data as *mut _ as *mut u8,
1502+
vp as *u8, data_size);
1503+
1504+
// we've transferred ownership of the contents from v, but we can't drop it
1505+
// as it still needs to free its own allocation.
1506+
v.set_len(0);
1507+
1508+
transmute(ret)
1509+
}
1510+
}
1511+
}
1512+
14681513
/// Unsafe operations
14691514
pub mod raw {
14701515
use super::Vec;
@@ -1488,7 +1533,8 @@ pub mod raw {
14881533
mod tests {
14891534
use prelude::*;
14901535
use mem::size_of;
1491-
use super::{unzip, raw};
1536+
use kinds::marker;
1537+
use super::{unzip, raw, FromVec};
14921538

14931539
#[test]
14941540
fn test_small_vec_struct() {
@@ -1765,4 +1811,30 @@ mod tests {
17651811
assert_eq!(d, vec![1, 2, 3, 4, 5]);
17661812
}
17671813
}
1814+
1815+
#[test]
1816+
fn test_from_vec() {
1817+
let a = vec![1u, 2, 3];
1818+
let b: ~[uint] = FromVec::from_vec(a);
1819+
assert_eq!(b.as_slice(), &[1u, 2, 3]);
1820+
1821+
let a = vec![];
1822+
let b: ~[u8] = FromVec::from_vec(a);
1823+
assert_eq!(b.as_slice(), &[]);
1824+
1825+
let a = vec!["one".to_owned(), "two".to_owned()];
1826+
let b: ~[~str] = FromVec::from_vec(a);
1827+
assert_eq!(b.as_slice(), &["one".to_owned(), "two".to_owned()]);
1828+
1829+
struct Foo {
1830+
x: uint,
1831+
nocopy: marker::NoCopy
1832+
}
1833+
1834+
let a = vec![Foo{x: 42, nocopy: marker::NoCopy}, Foo{x: 84, nocopy: marker::NoCopy}];
1835+
let b: ~[Foo] = FromVec::from_vec(a);
1836+
assert_eq!(b.len(), 2);
1837+
assert_eq!(b[0].x, 42);
1838+
assert_eq!(b[1].x, 84);
1839+
}
17681840
}

0 commit comments

Comments
 (0)