@@ -28,6 +28,7 @@ use ptr::RawPtr;
28
28
use ptr;
29
29
use rt:: global_heap:: { malloc_raw, realloc_raw} ;
30
30
use raw:: Slice ;
31
+ use RawVec = raw :: Vec ;
31
32
use slice:: { ImmutableEqVector , ImmutableVector , Items , MutItems , MutableVector } ;
32
33
use slice:: { MutableTotalOrdVector , OwnedVector , Vector } ;
33
34
use slice:: { MutableVectorAllocating } ;
@@ -1465,6 +1466,50 @@ pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
1465
1466
( ts, us)
1466
1467
}
1467
1468
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
+
1468
1513
/// Unsafe operations
1469
1514
pub mod raw {
1470
1515
use super :: Vec ;
@@ -1488,7 +1533,8 @@ pub mod raw {
1488
1533
mod tests {
1489
1534
use prelude:: * ;
1490
1535
use mem:: size_of;
1491
- use super :: { unzip, raw} ;
1536
+ use kinds:: marker;
1537
+ use super :: { unzip, raw, FromVec } ;
1492
1538
1493
1539
#[ test]
1494
1540
fn test_small_vec_struct ( ) {
@@ -1765,4 +1811,30 @@ mod tests {
1765
1811
assert_eq ! ( d, vec![ 1 , 2 , 3 , 4 , 5 ] ) ;
1766
1812
}
1767
1813
}
1814
+
1815
+ #[ test]
1816
+ fn test_from_vec ( ) {
1817
+ let a = vec ! [ 1 u, 2 , 3 ] ;
1818
+ let b: ~[ uint ] = FromVec :: from_vec ( a) ;
1819
+ assert_eq ! ( b. as_slice( ) , & [ 1 u, 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
+ }
1768
1840
}
0 commit comments