@@ -32,6 +32,7 @@ use core::cmp;
32
32
use alloc:: raw_vec:: RawVec ;
33
33
34
34
use super :: range:: RangeArgument ;
35
+ use super :: vec:: Vec ;
35
36
36
37
const INITIAL_CAPACITY : usize = 7 ; // 2^3 - 1
37
38
const MINIMUM_CAPACITY : usize = 1 ; // 2 - 1
@@ -2121,6 +2122,106 @@ impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
2121
2122
}
2122
2123
}
2123
2124
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
+
2124
2225
#[ cfg( test) ]
2125
2226
mod tests {
2126
2227
use core:: iter:: Iterator ;
@@ -2401,4 +2502,82 @@ mod tests {
2401
2502
}
2402
2503
}
2403
2504
}
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
+ }
2404
2583
}
0 commit comments