Skip to content

Commit 5be210c

Browse files
committed
Auto merge of #22058 - Gankro:all-the-impls, r=huonw
Working on just knocking these out for all the collections so that there's something there.
2 parents b63cee4 + 3c18bc4 commit 5be210c

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

src/libcollections/ring_buf.rs

+151
Original file line numberDiff line numberDiff line change
@@ -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

12941386
impl<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

Comments
 (0)