@@ -2043,6 +2043,146 @@ impl<T> VecDeque<T> {
20432043 }
20442044 }
20452045
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+
20462186 /// Rotates the double-ended queue `mid` places to the left.
20472187 ///
20482188 /// Equivalently,
@@ -2802,63 +2942,16 @@ impl<T> From<VecDeque<T>> for Vec<T> {
28022942 /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]);
28032943 /// assert_eq!(vec.as_ptr(), ptr);
28042944 /// ```
2805- fn from ( other : VecDeque < T > ) -> Self {
2945+ fn from ( mut other : VecDeque < T > ) -> Self {
2946+ other. make_contiguous ( ) ;
2947+
28062948 unsafe {
28072949 let buf = other. buf . ptr ( ) ;
28082950 let len = other. len ( ) ;
2809- let tail = other. tail ;
2810- let head = other. head ;
28112951 let cap = other. cap ( ) ;
28122952
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) ;
28622955 }
28632956 let out = Vec :: from_raw_parts ( buf, len, cap) ;
28642957 mem:: forget ( other) ;
0 commit comments