@@ -2043,6 +2043,146 @@ impl<T> VecDeque<T> {
2043
2043
}
2044
2044
}
2045
2045
2046
+ /// Rearranges the internal storage of this deque so it is one contiguous slice, which is then returned.
2047
+ ///
2048
+ /// This method does not allocate and does not change the order of the inserted elements.
2049
+ /// As it returns a mutable slice, this can be used to sort or binary search a deque.
2050
+ ///
2051
+ /// In case `self` is already contiguous, [`as_slices`](#method.as_slices) can be used to get immutable access.
2052
+ ///
2053
+ /// # Examples
2054
+ ///
2055
+ /// Sorting the content of a deque.
2056
+ ///
2057
+ /// ```
2058
+ /// #![feature(deque_make_contiguous)]
2059
+ ///
2060
+ /// use std::collections::VecDeque;
2061
+ ///
2062
+ /// let mut buf = VecDeque::with_capacity(15);
2063
+ ///
2064
+ /// buf.push_back(2);
2065
+ /// buf.push_back(1);
2066
+ /// buf.push_front(3);
2067
+ ///
2068
+ /// // sorting the deque
2069
+ /// buf.make_contiguous().sort();
2070
+ /// assert_eq!(buf.as_slices(), (&[1, 2, 3] as &[_], &[] as &[_]));
2071
+ ///
2072
+ /// // sorting it in reverse order
2073
+ /// buf.make_contiguous().sort_by(|a, b| b.cmp(a));
2074
+ /// assert_eq!(buf.as_slices(), (&[3, 2, 1] as &[_], &[] as &[_]));
2075
+ /// ```
2076
+ ///
2077
+ /// Getting immutable access to the contiguous slice.
2078
+ ///
2079
+ /// ```rust
2080
+ /// #![feature(deque_make_contiguous)]
2081
+ ///
2082
+ /// use std::collections::VecDeque;
2083
+ ///
2084
+ /// let mut buf = VecDeque::new();
2085
+ ///
2086
+ /// buf.push_back(2);
2087
+ /// buf.push_back(1);
2088
+ /// buf.push_front(3);
2089
+ ///
2090
+ /// buf.make_contiguous();
2091
+ /// if let (slice, &[]) = buf.as_slices() {
2092
+ /// // we can now be sure that `slice` contains all elements of the deque,
2093
+ /// // while still having immutable access to `buf`.
2094
+ /// assert_eq!(buf.len(), slice.len());
2095
+ /// assert_eq!(slice, &[3, 2, 1] as &[_]);
2096
+ /// }
2097
+ /// ```
2098
+ #[ unstable( feature = "deque_make_contiguous" , issue = "none" ) ]
2099
+ pub fn make_contiguous ( & mut self ) -> & mut [ T ] {
2100
+ if self . is_contiguous ( ) {
2101
+ let tail = self . tail ;
2102
+ let head = self . head ;
2103
+ return unsafe { & mut self . buffer_as_mut_slice ( ) [ tail..head] } ;
2104
+ }
2105
+
2106
+ let buf = self . buf . ptr ( ) ;
2107
+ let cap = self . cap ( ) ;
2108
+ let len = self . len ( ) ;
2109
+
2110
+ let free = self . tail - self . head ;
2111
+ let tail_len = cap - self . tail ;
2112
+
2113
+ if free >= tail_len {
2114
+ // there is enough free space to copy the tail in one go,
2115
+ // this means that we first shift the head backwards, and then
2116
+ // copy the tail to the correct position.
2117
+ //
2118
+ // from: DEFGH....ABC
2119
+ // to: ABCDEFGH....
2120
+ unsafe {
2121
+ ptr:: copy ( buf, buf. add ( tail_len) , self . head ) ;
2122
+ // ...DEFGH.ABC
2123
+ ptr:: copy_nonoverlapping ( buf. add ( self . tail ) , buf, tail_len) ;
2124
+ // ABCDEFGH....
2125
+
2126
+ self . tail = 0 ;
2127
+ self . head = len;
2128
+ }
2129
+ } else if free >= self . head {
2130
+ // there is enough free space to copy the head in one go,
2131
+ // this means that we first shift the tail forwards, and then
2132
+ // copy the head to the correct position.
2133
+ //
2134
+ // from: FGH....ABCDE
2135
+ // to: ...ABCDEFGH.
2136
+ unsafe {
2137
+ ptr:: copy ( buf. add ( self . tail ) , buf. add ( self . head ) , tail_len) ;
2138
+ // FGHABCDE....
2139
+ ptr:: copy_nonoverlapping ( buf, buf. add ( self . head + tail_len) , self . head ) ;
2140
+ // ...ABCDEFGH.
2141
+
2142
+ self . tail = self . head ;
2143
+ self . head = self . tail + len;
2144
+ }
2145
+ } else {
2146
+ // free is smaller than both head and tail,
2147
+ // this means we have to slowly "swap" the tail and the head.
2148
+ //
2149
+ // from: EFGHI...ABCD or HIJK.ABCDEFG
2150
+ // to: ABCDEFGHI... or ABCDEFGHIJK.
2151
+ let mut left_edge: usize = 0 ;
2152
+ let mut right_edge: usize = self . tail ;
2153
+ unsafe {
2154
+ // The general problem looks like this
2155
+ // GHIJKLM...ABCDEF - before any swaps
2156
+ // ABCDEFM...GHIJKL - after 1 pass of swaps
2157
+ // ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
2158
+ // - then restart the algorithm with a new (smaller) store
2159
+ // Sometimes the temp store is reached when the right edge is at the end
2160
+ // of the buffer - this means we've hit the right order with fewer swaps!
2161
+ // E.g
2162
+ // EF..ABCD
2163
+ // ABCDEF.. - after four only swaps we've finished
2164
+ while left_edge < len && right_edge != cap {
2165
+ let mut right_offset = 0 ;
2166
+ for i in left_edge..right_edge {
2167
+ right_offset = ( i - left_edge) % ( cap - right_edge) ;
2168
+ let src: isize = ( right_edge + right_offset) as isize ;
2169
+ ptr:: swap ( buf. add ( i) , buf. offset ( src) ) ;
2170
+ }
2171
+ let n_ops = right_edge - left_edge;
2172
+ left_edge += n_ops;
2173
+ right_edge += right_offset + 1 ;
2174
+ }
2175
+
2176
+ self . tail = 0 ;
2177
+ self . head = len;
2178
+ }
2179
+ }
2180
+
2181
+ let tail = self . tail ;
2182
+ let head = self . head ;
2183
+ unsafe { & mut self . buffer_as_mut_slice ( ) [ tail..head] }
2184
+ }
2185
+
2046
2186
/// Rotates the double-ended queue `mid` places to the left.
2047
2187
///
2048
2188
/// Equivalently,
@@ -2802,63 +2942,16 @@ impl<T> From<VecDeque<T>> for Vec<T> {
2802
2942
/// assert_eq!(vec, [8, 9, 1, 2, 3, 4]);
2803
2943
/// assert_eq!(vec.as_ptr(), ptr);
2804
2944
/// ```
2805
- fn from ( other : VecDeque < T > ) -> Self {
2945
+ fn from ( mut other : VecDeque < T > ) -> Self {
2946
+ other. make_contiguous ( ) ;
2947
+
2806
2948
unsafe {
2807
2949
let buf = other. buf . ptr ( ) ;
2808
2950
let len = other. len ( ) ;
2809
- let tail = other. tail ;
2810
- let head = other. head ;
2811
2951
let cap = other. cap ( ) ;
2812
2952
2813
- // Need to move the ring to the front of the buffer, as vec will expect this.
2814
- if other. is_contiguous ( ) {
2815
- ptr:: copy ( buf. add ( tail) , buf, len) ;
2816
- } else {
2817
- if ( tail - head) >= cmp:: min ( cap - tail, head) {
2818
- // There is enough free space in the centre for the shortest block so we can
2819
- // do this in at most three copy moves.
2820
- if ( cap - tail) > head {
2821
- // right hand block is the long one; move that enough for the left
2822
- ptr:: copy ( buf. add ( tail) , buf. add ( tail - head) , cap - tail) ;
2823
- // copy left in the end
2824
- ptr:: copy ( buf, buf. add ( cap - head) , head) ;
2825
- // shift the new thing to the start
2826
- ptr:: copy ( buf. add ( tail - head) , buf, len) ;
2827
- } else {
2828
- // left hand block is the long one, we can do it in two!
2829
- ptr:: copy ( buf, buf. add ( cap - tail) , head) ;
2830
- ptr:: copy ( buf. add ( tail) , buf, cap - tail) ;
2831
- }
2832
- } else {
2833
- // Need to use N swaps to move the ring
2834
- // We can use the space at the end of the ring as a temp store
2835
-
2836
- let mut left_edge: usize = 0 ;
2837
- let mut right_edge: usize = tail;
2838
-
2839
- // The general problem looks like this
2840
- // GHIJKLM...ABCDEF - before any swaps
2841
- // ABCDEFM...GHIJKL - after 1 pass of swaps
2842
- // ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
2843
- // - then restart the algorithm with a new (smaller) store
2844
- // Sometimes the temp store is reached when the right edge is at the end
2845
- // of the buffer - this means we've hit the right order with fewer swaps!
2846
- // E.g
2847
- // EF..ABCD
2848
- // ABCDEF.. - after four only swaps we've finished
2849
-
2850
- while left_edge < len && right_edge != cap {
2851
- let mut right_offset = 0 ;
2852
- for i in left_edge..right_edge {
2853
- right_offset = ( i - left_edge) % ( cap - right_edge) ;
2854
- let src: isize = ( right_edge + right_offset) as isize ;
2855
- ptr:: swap ( buf. add ( i) , buf. offset ( src) ) ;
2856
- }
2857
- let n_ops = right_edge - left_edge;
2858
- left_edge += n_ops;
2859
- right_edge += right_offset + 1 ;
2860
- }
2861
- }
2953
+ if other. head != 0 {
2954
+ ptr:: copy ( buf. add ( other. tail ) , buf, len) ;
2862
2955
}
2863
2956
let out = Vec :: from_raw_parts ( buf, len, cap) ;
2864
2957
mem:: forget ( other) ;
0 commit comments