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