@@ -32,6 +32,7 @@ use core::cmp;
3232use alloc:: raw_vec:: RawVec ;
3333
3434use super :: range:: RangeArgument ;
35+ use super :: vec:: Vec ;
3536
3637const INITIAL_CAPACITY : usize = 7 ; // 2^3 - 1
3738const MINIMUM_CAPACITY : usize = 1 ; // 2 - 1
@@ -2121,6 +2122,106 @@ impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
21212122 }
21222123}
21232124
2125+ #[ stable( feature = "vecdeque_vec_conversions" , since = "1.10.0" ) ]
2126+ impl < T > From < Vec < T > > for VecDeque < T > {
2127+ fn from ( mut other : Vec < T > ) -> Self {
2128+ unsafe {
2129+ let other_buf = other. as_mut_ptr ( ) ;
2130+ let mut buf = RawVec :: from_raw_parts ( other_buf, other. capacity ( ) ) ;
2131+ let len = other. len ( ) ;
2132+ mem:: forget ( other) ;
2133+
2134+ // We need to extend the buf if it's not a power of two, too small
2135+ // or doesn't have at least one free space
2136+ if !buf. cap ( ) . is_power_of_two ( )
2137+ || ( buf. cap ( ) < ( MINIMUM_CAPACITY + 1 ) )
2138+ || ( buf. cap ( ) == len)
2139+ {
2140+ let cap = cmp:: max ( buf. cap ( ) + 1 , MINIMUM_CAPACITY + 1 ) . next_power_of_two ( ) ;
2141+ buf. reserve_exact ( len, cap - len) ;
2142+ }
2143+
2144+ VecDeque {
2145+ tail : 0 ,
2146+ head : len,
2147+ buf : buf
2148+ }
2149+ }
2150+ }
2151+ }
2152+
2153+ #[ stable( feature = "vecdeque_vec_conversions" , since = "1.10.0" ) ]
2154+ impl < T > From < VecDeque < T > > for Vec < T > {
2155+ fn from ( other : VecDeque < T > ) -> Self {
2156+ unsafe {
2157+ let buf = other. buf . ptr ( ) ;
2158+ let len = other. len ( ) ;
2159+ let tail = other. tail ;
2160+ let head = other. head ;
2161+ let cap = other. cap ( ) ;
2162+
2163+ // Need to move the ring to the front of the buffer, as vec will expect this.
2164+ if other. is_contiguous ( ) {
2165+ ptr:: copy ( buf. offset ( tail as isize ) , buf, len) ;
2166+ } else {
2167+ if ( tail - head) >= cmp:: min ( ( cap - tail) , head) {
2168+ // There is enough free space in the centre for the shortest block so we can
2169+ // do this in at most three copy moves.
2170+ if ( cap - tail) > head {
2171+ // right hand block is the long one; move that enough for the left
2172+ ptr:: copy (
2173+ buf. offset ( tail as isize ) ,
2174+ buf. offset ( ( tail - head) as isize ) ,
2175+ cap - tail) ;
2176+ // copy left in the end
2177+ ptr:: copy ( buf, buf. offset ( ( cap - head) as isize ) , head) ;
2178+ // shift the new thing to the start
2179+ ptr:: copy ( buf. offset ( ( tail-head) as isize ) , buf, len) ;
2180+ } else {
2181+ // left hand block is the long one, we can do it in two!
2182+ ptr:: copy ( buf, buf. offset ( ( cap-tail) as isize ) , head) ;
2183+ ptr:: copy ( buf. offset ( tail as isize ) , buf, cap-tail) ;
2184+ }
2185+ } else {
2186+ // Need to use N swaps to move the ring
2187+ // We can use the space at the end of the ring as a temp store
2188+
2189+ let mut left_edge: usize = 0 ;
2190+ let mut right_edge: usize = tail;
2191+
2192+ // The general problem looks like this
2193+ // GHIJKLM...ABCDEF - before any swaps
2194+ // ABCDEFM...GHIJKL - after 1 pass of swaps
2195+ // ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
2196+ // - then restart the algorithm with a new (smaller) store
2197+ // Sometimes the temp store is reached when the right edge is at the end
2198+ // of the buffer - this means we've hit the right order with fewer swaps!
2199+ // E.g
2200+ // EF..ABCD
2201+ // ABCDEF.. - after four only swaps we've finished
2202+
2203+ while left_edge < len && right_edge != cap {
2204+ let mut right_offset = 0 ;
2205+ for i in left_edge..right_edge {
2206+ right_offset = ( i - left_edge) % ( cap - right_edge) ;
2207+ let src: isize = ( right_edge + right_offset) as isize ;
2208+ ptr:: swap ( buf. offset ( i as isize ) , buf. offset ( src) ) ;
2209+ }
2210+ let n_ops = right_edge - left_edge;
2211+ left_edge += n_ops;
2212+ right_edge += right_offset + 1 ;
2213+
2214+ }
2215+ }
2216+
2217+ }
2218+ let out = Vec :: from_raw_parts ( buf, len, cap) ;
2219+ mem:: forget ( other) ;
2220+ out
2221+ }
2222+ }
2223+ }
2224+
21242225#[ cfg( test) ]
21252226mod tests {
21262227 use core:: iter:: Iterator ;
@@ -2401,4 +2502,82 @@ mod tests {
24012502 }
24022503 }
24032504 }
2505+
2506+ #[ test]
2507+ fn test_from_vec ( ) {
2508+ use super :: super :: vec:: Vec ;
2509+ for cap in 0 ..35 {
2510+ for len in 0 ..cap + 1 {
2511+ let mut vec = Vec :: with_capacity ( cap) ;
2512+ vec. extend ( 0 ..len) ;
2513+
2514+ let vd = VecDeque :: from ( vec. clone ( ) ) ;
2515+ assert ! ( vd. cap( ) . is_power_of_two( ) ) ;
2516+ assert_eq ! ( vd. len( ) , vec. len( ) ) ;
2517+ assert ! ( vd. into_iter( ) . eq( vec) ) ;
2518+ }
2519+ }
2520+ }
2521+
2522+ #[ test]
2523+ fn test_vec_from_vecdeque ( ) {
2524+ use super :: super :: vec:: Vec ;
2525+
2526+ fn create_vec_and_test_convert ( cap : usize , offset : usize , len : usize ) {
2527+ let mut vd = VecDeque :: with_capacity ( cap) ;
2528+ for _ in 0 ..offset {
2529+ vd. push_back ( 0 ) ;
2530+ vd. pop_front ( ) ;
2531+ }
2532+ vd. extend ( 0 ..len) ;
2533+
2534+ let vec: Vec < _ > = Vec :: from ( vd. clone ( ) ) ;
2535+ assert_eq ! ( vec. len( ) , vd. len( ) ) ;
2536+ assert ! ( vec. into_iter( ) . eq( vd) ) ;
2537+ }
2538+
2539+ for cap_pwr in 0 ..7 {
2540+ // Make capacity as a (2^x)-1, so that the ring size is 2^x
2541+ let cap = ( 2i32 . pow ( cap_pwr) - 1 ) as usize ;
2542+
2543+ // In these cases there is enough free space to solve it with copies
2544+ for len in 0 ..( ( cap+1 ) /2 ) {
2545+ // Test contiguous cases
2546+ for offset in 0 ..( cap-len) {
2547+ create_vec_and_test_convert ( cap, offset, len)
2548+ }
2549+
2550+ // Test cases where block at end of buffer is bigger than block at start
2551+ for offset in ( cap-len) ..( cap-( len/2 ) ) {
2552+ create_vec_and_test_convert ( cap, offset, len)
2553+ }
2554+
2555+ // Test cases where block at start of buffer is bigger than block at end
2556+ for offset in ( cap-( len/2 ) ) ..cap {
2557+ create_vec_and_test_convert ( cap, offset, len)
2558+ }
2559+ }
2560+
2561+ // Now there's not (necessarily) space to straighten the ring with simple copies,
2562+ // the ring will use swapping when:
2563+ // (cap + 1 - offset) > (cap + 1 - len) && (len - (cap + 1 - offset)) > (cap + 1 - len))
2564+ // right block size > free space && left block size > free space
2565+ for len in ( ( cap+1 ) /2 ) ..cap {
2566+ // Test contiguous cases
2567+ for offset in 0 ..( cap-len) {
2568+ create_vec_and_test_convert ( cap, offset, len)
2569+ }
2570+
2571+ // Test cases where block at end of buffer is bigger than block at start
2572+ for offset in ( cap-len) ..( cap-( len/2 ) ) {
2573+ create_vec_and_test_convert ( cap, offset, len)
2574+ }
2575+
2576+ // Test cases where block at start of buffer is bigger than block at end
2577+ for offset in ( cap-( len/2 ) ) ..cap {
2578+ create_vec_and_test_convert ( cap, offset, len)
2579+ }
2580+ }
2581+ }
2582+ }
24042583}
0 commit comments