@@ -959,6 +959,9 @@ impl<T> VecDeque<T> {
959959 /// Returns a pair of slices which contain, in order, the contents of the
960960 /// `VecDeque`.
961961 ///
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+ ///
962965 /// # Examples
963966 ///
964967 /// ```
@@ -989,6 +992,9 @@ impl<T> VecDeque<T> {
989992 /// Returns a pair of slices which contain, in order, the contents of the
990993 /// `VecDeque`.
991994 ///
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+ ///
992998 /// # Examples
993999 ///
9941000 /// ```
@@ -2044,6 +2050,148 @@ impl<T> VecDeque<T> {
20442050 }
20452051 }
20462052
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+
20472195 /// Rotates the double-ended queue `mid` places to the left.
20482196 ///
20492197 /// Equivalently,
@@ -2803,63 +2951,16 @@ impl<T> From<VecDeque<T>> for Vec<T> {
28032951 /// assert_eq!(vec, [8, 9, 1, 2, 3, 4]);
28042952 /// assert_eq!(vec.as_ptr(), ptr);
28052953 /// ```
2806- fn from ( other : VecDeque < T > ) -> Self {
2954+ fn from ( mut other : VecDeque < T > ) -> Self {
2955+ other. make_contiguous ( ) ;
2956+
28072957 unsafe {
28082958 let buf = other. buf . ptr ( ) ;
28092959 let len = other. len ( ) ;
2810- let tail = other. tail ;
2811- let head = other. head ;
28122960 let cap = other. cap ( ) ;
28132961
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) ;
28632964 }
28642965 let out = Vec :: from_raw_parts ( buf, len, cap) ;
28652966 mem:: forget ( other) ;
0 commit comments