@@ -1289,6 +1289,98 @@ impl<T> RingBuf<T> {
12891289
12901290 return elem;
12911291 }
1292+
1293+ /// Splits the collection into two at the given index.
1294+ ///
1295+ /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
1296+ /// and the returned `Self` contains elements `[at, len)`.
1297+ ///
1298+ /// Note that the capacity of `self` does not change.
1299+ ///
1300+ /// # Panics
1301+ ///
1302+ /// Panics if `at > len`
1303+ ///
1304+ /// # Examples
1305+ ///
1306+ /// ```
1307+ /// use std::collections::RingBuf;
1308+ ///
1309+ /// let mut buf: RingBuf<_> = vec![1,2,3].into_iter().collect();
1310+ /// let buf2 = buf.split_off(1);
1311+ /// // buf = [1], buf2 = [2, 3]
1312+ /// assert_eq!(buf.len(), 1);
1313+ /// assert_eq!(buf2.len(), 2);
1314+ /// ```
1315+ #[ inline]
1316+ #[ unstable( feature = "collections" ,
1317+ reason = "new API, waiting for dust to settle" ) ]
1318+ pub fn split_off ( & mut self , at : usize ) -> Self {
1319+ let len = self . len ( ) ;
1320+ assert ! ( at <= len, "`at` out of bounds" ) ;
1321+
1322+ let other_len = len - at;
1323+ let mut other = RingBuf :: with_capacity ( other_len) ;
1324+
1325+ unsafe {
1326+ let ( first_half, second_half) = self . as_slices ( ) ;
1327+
1328+ let first_len = first_half. len ( ) ;
1329+ let second_len = second_half. len ( ) ;
1330+ if at < first_len {
1331+ // `at` lies in the first half.
1332+ let amount_in_first = first_len - at;
1333+
1334+ ptr:: copy_nonoverlapping_memory ( other. ptr ,
1335+ first_half. as_ptr ( ) . offset ( at as isize ) ,
1336+ amount_in_first) ;
1337+
1338+ // just take all of the second half.
1339+ ptr:: copy_nonoverlapping_memory ( other. ptr . offset ( amount_in_first as isize ) ,
1340+ second_half. as_ptr ( ) ,
1341+ second_len) ;
1342+ } else {
1343+ // `at` lies in the second half, need to factor in the elements we skipped
1344+ // in the first half.
1345+ let offset = at - first_len;
1346+ let amount_in_second = second_len - offset;
1347+ ptr:: copy_nonoverlapping_memory ( other. ptr ,
1348+ second_half. as_ptr ( ) . offset ( offset as isize ) ,
1349+ amount_in_second) ;
1350+ }
1351+ }
1352+
1353+ // Cleanup where the ends of the buffers are
1354+ self . head = self . wrap_index ( self . head - other_len) ;
1355+ other. head = other. wrap_index ( other_len) ;
1356+
1357+ other
1358+ }
1359+
1360+ /// Moves all the elements of `other` into `Self`, leaving `other` empty.
1361+ ///
1362+ /// # Panics
1363+ ///
1364+ /// Panics if the new number of elements in self overflows a `usize`.
1365+ ///
1366+ /// # Examples
1367+ ///
1368+ /// ```
1369+ /// use std::collections::RingBuf;
1370+ ///
1371+ /// let mut buf: RingBuf<_> = vec![1, 2, 3].into_iter().collect();
1372+ /// let mut buf2: RingBuf<_> = vec![4, 5, 6].into_iter().collect();
1373+ /// buf.append(&mut buf2);
1374+ /// assert_eq!(buf.len(), 6);
1375+ /// assert_eq!(buf2.len(), 0);
1376+ /// ```
1377+ #[ inline]
1378+ #[ unstable( feature = "collections" ,
1379+ reason = "new API, waiting for dust to settle" ) ]
1380+ pub fn append ( & mut self , other : & mut Self ) {
1381+ // naive impl
1382+ self . extend ( other. drain ( ) ) ;
1383+ }
12921384}
12931385
12941386impl < T : Clone > RingBuf < T > {
@@ -2711,4 +2803,63 @@ mod tests {
27112803 assert_eq ! ( ring. len( ) as i32 , cap) ;
27122804 assert_eq ! ( ring. capacity( ) as i32 , cap) ;
27132805 }
2806+
2807+ #[ test]
2808+ fn test_split_off ( ) {
2809+ // This test checks that every single combination of tail position, length, and
2810+ // split position is tested. Capacity 15 should be large enough to cover every case.
2811+
2812+ let mut tester = RingBuf :: with_capacity ( 15 ) ;
2813+ // can't guarantee we got 15, so have to get what we got.
2814+ // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
2815+ // this test isn't covering what it wants to
2816+ let cap = tester. capacity ( ) ;
2817+
2818+ // len is the length *before* splitting
2819+ for len in 0 ..cap {
2820+ // index to split at
2821+ for at in 0 ..len + 1 {
2822+ // 0, 1, 2, .., at - 1 (may be empty)
2823+ let expected_self = iter:: count ( 0 , 1 ) . take ( at) . collect ( ) ;
2824+ // at, at + 1, .., len - 1 (may be empty)
2825+ let expected_other = iter:: count ( at, 1 ) . take ( len - at) . collect ( ) ;
2826+
2827+ for tail_pos in 0 ..cap {
2828+ tester. tail = tail_pos;
2829+ tester. head = tail_pos;
2830+ for i in 0 ..len {
2831+ tester. push_back ( i) ;
2832+ }
2833+ let result = tester. split_off ( at) ;
2834+ assert ! ( tester. tail < tester. cap) ;
2835+ assert ! ( tester. head < tester. cap) ;
2836+ assert ! ( result. tail < result. cap) ;
2837+ assert ! ( result. head < result. cap) ;
2838+ assert_eq ! ( tester, expected_self) ;
2839+ assert_eq ! ( result, expected_other) ;
2840+ }
2841+ }
2842+ }
2843+ }
2844+
2845+ #[ test]
2846+ fn test_append ( ) {
2847+ let mut a: RingBuf < _ > = vec ! [ 1 , 2 , 3 ] . into_iter ( ) . collect ( ) ;
2848+ let mut b: RingBuf < _ > = vec ! [ 4 , 5 , 6 ] . into_iter ( ) . collect ( ) ;
2849+
2850+ // normal append
2851+ a. append ( & mut b) ;
2852+ assert_eq ! ( a. iter( ) . cloned( ) . collect( ) , vec![ 1 , 2 , 3 , 4 , 5 , 6 ] ) ;
2853+ assert_eq ! ( b. iter( ) . cloned( ) . collect( ) , vec![ ] ) ;
2854+
2855+ // append nothing to something
2856+ a. append ( & mut b) ;
2857+ assert_eq ! ( a. iter( ) . cloned( ) . collect( ) , vec![ 1 , 2 , 3 , 4 , 5 , 6 ] ) ;
2858+ assert_eq ! ( b. iter( ) . cloned( ) . collect( ) , vec![ ] ) ;
2859+
2860+ // append something to nothing
2861+ b. append ( & mut a) ;
2862+ assert_eq ! ( b. iter( ) . cloned( ) . collect( ) , vec![ 1 , 2 , 3 , 4 , 5 , 6 ] ) ;
2863+ assert_eq ! ( a. iter( ) . cloned( ) . collect( ) , vec![ ] ) ;
2864+ }
27142865}
0 commit comments