Skip to content

Commit eb35f95

Browse files
committed
Add splice to thin_vec
The impl is a copy-paste of the one in std. Seemingly no significant modifications were necessary.
1 parent 3dcaf54 commit eb35f95

File tree

1 file changed

+251
-58
lines changed

1 file changed

+251
-58
lines changed

src/lib.rs

Lines changed: 251 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,53 @@ impl<T> ThinVec<T> {
14211421
}
14221422
}
14231423

1424+
/// Creates a splicing iterator that replaces the specified range in the vector
1425+
/// with the given `replace_with` iterator and yields the removed items.
1426+
/// `replace_with` does not need to be the same length as `range`.
1427+
///
1428+
/// `range` is removed even if the iterator is not consumed until the end.
1429+
///
1430+
/// It is unspecified how many elements are removed from the vector
1431+
/// if the `Splice` value is leaked.
1432+
///
1433+
/// The input iterator `replace_with` is only consumed when the `Splice` value is dropped.
1434+
///
1435+
/// This is optimal if:
1436+
///
1437+
/// * The tail (elements in the vector after `range`) is empty,
1438+
/// * or `replace_with` yields fewer or equal elements than `range`’s length
1439+
/// * or the lower bound of its `size_hint()` is exact.
1440+
///
1441+
/// Otherwise, a temporary vector is allocated and the tail is moved twice.
1442+
///
1443+
/// # Panics
1444+
///
1445+
/// Panics if the starting point is greater than the end point or if
1446+
/// the end point is greater than the length of the vector.
1447+
///
1448+
/// # Examples
1449+
///
1450+
/// ```
1451+
/// use thin_vec::{ThinVec, thin_vec};
1452+
///
1453+
/// let mut v = thin_vec![1, 2, 3, 4];
1454+
/// let new = [7, 8, 9];
1455+
/// let u: ThinVec<_> = v.splice(1..3, new).collect();
1456+
/// assert_eq!(v, &[1, 7, 8, 9, 4]);
1457+
/// assert_eq!(u, &[2, 3]);
1458+
/// ```
1459+
#[inline]
1460+
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
1461+
where
1462+
R: RangeBounds<usize>,
1463+
I: IntoIterator<Item = T>,
1464+
{
1465+
Splice {
1466+
drain: self.drain(range),
1467+
replace_with: replace_with.into_iter(),
1468+
}
1469+
}
1470+
14241471
/// Resize the buffer and update its capacity, without changing the length.
14251472
/// Unsafe because it can cause length to be greater than capacity.
14261473
unsafe fn reallocate(&mut self, new_cap: usize) {
@@ -2397,6 +2444,133 @@ impl<'a, T> AsRef<[T]> for Drain<'a, T> {
23972444
}
23982445
}
23992446

2447+
/// A splicing iterator for `ThinVec`.
2448+
///
2449+
/// This struct is created by [`ThinVec::splice`][].
2450+
/// See its documentation for more.
2451+
///
2452+
/// # Example
2453+
///
2454+
/// ```
2455+
/// use thin_vec::thin_vec;
2456+
///
2457+
/// let mut v = thin_vec![0, 1, 2];
2458+
/// let new = [7, 8];
2459+
/// let iter: thin_vec::Splice<_> = v.splice(1.., new);
2460+
/// ```
2461+
#[derive(Debug)]
2462+
pub struct Splice<'a, I: Iterator + 'a> {
2463+
drain: Drain<'a, I::Item>,
2464+
replace_with: I,
2465+
}
2466+
2467+
impl<I: Iterator> Iterator for Splice<'_, I> {
2468+
type Item = I::Item;
2469+
2470+
fn next(&mut self) -> Option<Self::Item> {
2471+
self.drain.next()
2472+
}
2473+
2474+
fn size_hint(&self) -> (usize, Option<usize>) {
2475+
self.drain.size_hint()
2476+
}
2477+
}
2478+
2479+
impl<I: Iterator> DoubleEndedIterator for Splice<'_, I> {
2480+
fn next_back(&mut self) -> Option<Self::Item> {
2481+
self.drain.next_back()
2482+
}
2483+
}
2484+
2485+
impl<I: Iterator> ExactSizeIterator for Splice<'_, I> {}
2486+
2487+
impl<I: Iterator> Drop for Splice<'_, I> {
2488+
fn drop(&mut self) {
2489+
// Ensure we've fully drained out the range
2490+
self.drain.by_ref().for_each(drop);
2491+
2492+
unsafe {
2493+
// If there's no tail elements, then the inner ThinVec is already
2494+
// correct and we can just extend it like normal.
2495+
if self.drain.tail == 0 {
2496+
(*self.drain.vec).extend(self.replace_with.by_ref());
2497+
return;
2498+
}
2499+
2500+
// First fill the range left by drain().
2501+
if !self.drain.fill(&mut self.replace_with) {
2502+
return;
2503+
}
2504+
2505+
// There may be more elements. Use the lower bound as an estimate.
2506+
let (lower_bound, _upper_bound) = self.replace_with.size_hint();
2507+
if lower_bound > 0 {
2508+
self.drain.move_tail(lower_bound);
2509+
if !self.drain.fill(&mut self.replace_with) {
2510+
return;
2511+
}
2512+
}
2513+
2514+
// Collect any remaining elements.
2515+
// This is a zero-length vector which does not allocate if `lower_bound` was exact.
2516+
let mut collected = self
2517+
.replace_with
2518+
.by_ref()
2519+
.collect::<Vec<I::Item>>()
2520+
.into_iter();
2521+
// Now we have an exact count.
2522+
if collected.len() > 0 {
2523+
self.drain.move_tail(collected.len());
2524+
let filled = self.drain.fill(&mut collected);
2525+
debug_assert!(filled);
2526+
debug_assert_eq!(collected.len(), 0);
2527+
}
2528+
}
2529+
// Let `Drain::drop` move the tail back if necessary and restore `vec.len`.
2530+
}
2531+
}
2532+
2533+
/// Private helper methods for `Splice::drop`
2534+
impl<T> Drain<'_, T> {
2535+
/// The range from `self.vec.len` to `self.tail_start` contains elements
2536+
/// that have been moved out.
2537+
/// Fill that range as much as possible with new elements from the `replace_with` iterator.
2538+
/// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
2539+
unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
2540+
let vec = unsafe { &mut *self.vec };
2541+
let range_start = vec.len();
2542+
let range_end = self.end;
2543+
let range_slice = unsafe {
2544+
slice::from_raw_parts_mut(vec.data_raw().add(range_start), range_end - range_start)
2545+
};
2546+
2547+
for place in range_slice {
2548+
if let Some(new_item) = replace_with.next() {
2549+
unsafe { ptr::write(place, new_item) };
2550+
vec.set_len(vec.len() + 1);
2551+
} else {
2552+
return false;
2553+
}
2554+
}
2555+
true
2556+
}
2557+
2558+
/// Makes room for inserting more elements before the tail.
2559+
unsafe fn move_tail(&mut self, additional: usize) {
2560+
let vec = unsafe { &mut *self.vec };
2561+
let len = self.end + self.tail;
2562+
vec.reserve(len.checked_add(additional).expect("capacity overflow"));
2563+
2564+
let new_tail_start = self.end + additional;
2565+
unsafe {
2566+
let src = vec.data_raw().add(self.end);
2567+
let dst = vec.data_raw().add(new_tail_start);
2568+
ptr::copy(src, dst, self.tail);
2569+
}
2570+
self.end = new_tail_start;
2571+
}
2572+
}
2573+
24002574
/// Write is implemented for `ThinVec<u8>` by appending to the vector.
24012575
/// The vector will grow as needed.
24022576
/// This implementation is identical to the one for `Vec<u8>`.
@@ -2633,6 +2807,19 @@ mod tests {
26332807
assert_eq!(&v[..], &[]);
26342808
}
26352809

2810+
{
2811+
let mut v = ThinVec::<i32>::new();
2812+
assert_eq!(v.splice(.., []).len(), 0);
2813+
2814+
for _ in v.splice(.., []) {
2815+
unreachable!()
2816+
}
2817+
2818+
assert_eq!(v.len(), 0);
2819+
assert_eq!(v.capacity(), 0);
2820+
assert_eq!(&v[..], &[]);
2821+
}
2822+
26362823
{
26372824
let mut v = ThinVec::<i32>::new();
26382825
v.truncate(1);
@@ -3387,70 +3574,76 @@ mod std_tests {
33873574
v.drain(5..=5);
33883575
}
33893576

3390-
/* TODO: implement splice?
3391-
#[test]
3392-
fn test_splice() {
3393-
let mut v = thin_vec![1, 2, 3, 4, 5];
3394-
let a = [10, 11, 12];
3395-
v.splice(2..4, a.iter().cloned());
3396-
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3397-
v.splice(1..3, Some(20));
3398-
assert_eq!(v, &[1, 20, 11, 12, 5]);
3399-
}
3577+
#[test]
3578+
fn test_splice() {
3579+
let mut v = thin_vec![1, 2, 3, 4, 5];
3580+
let a = [10, 11, 12];
3581+
v.splice(2..4, a.iter().cloned());
3582+
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3583+
v.splice(1..3, Some(20));
3584+
assert_eq!(v, &[1, 20, 11, 12, 5]);
3585+
}
34003586

3401-
#[test]
3402-
fn test_splice_inclusive_range() {
3403-
let mut v = thin_vec![1, 2, 3, 4, 5];
3404-
let a = [10, 11, 12];
3405-
let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
3406-
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3407-
assert_eq!(t1, &[3, 4]);
3408-
let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
3409-
assert_eq!(v, &[1, 20, 11, 12, 5]);
3410-
assert_eq!(t2, &[2, 10]);
3411-
}
3587+
#[test]
3588+
fn test_splice_inclusive_range() {
3589+
let mut v = thin_vec![1, 2, 3, 4, 5];
3590+
let a = [10, 11, 12];
3591+
let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
3592+
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3593+
assert_eq!(t1, &[3, 4]);
3594+
let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
3595+
assert_eq!(v, &[1, 20, 11, 12, 5]);
3596+
assert_eq!(t2, &[2, 10]);
3597+
}
34123598

3413-
#[test]
3414-
#[should_panic]
3415-
fn test_splice_out_of_bounds() {
3416-
let mut v = thin_vec![1, 2, 3, 4, 5];
3417-
let a = [10, 11, 12];
3418-
v.splice(5..6, a.iter().cloned());
3419-
}
3599+
#[test]
3600+
#[should_panic]
3601+
fn test_splice_out_of_bounds() {
3602+
let mut v = thin_vec![1, 2, 3, 4, 5];
3603+
let a = [10, 11, 12];
3604+
v.splice(5..6, a.iter().cloned());
3605+
}
34203606

3421-
#[test]
3422-
#[should_panic]
3423-
fn test_splice_inclusive_out_of_bounds() {
3424-
let mut v = thin_vec![1, 2, 3, 4, 5];
3425-
let a = [10, 11, 12];
3426-
v.splice(5..=5, a.iter().cloned());
3427-
}
3607+
#[test]
3608+
#[should_panic]
3609+
fn test_splice_inclusive_out_of_bounds() {
3610+
let mut v = thin_vec![1, 2, 3, 4, 5];
3611+
let a = [10, 11, 12];
3612+
v.splice(5..=5, a.iter().cloned());
3613+
}
34283614

3429-
#[test]
3430-
fn test_splice_items_zero_sized() {
3431-
let mut vec = thin_vec![(), (), ()];
3432-
let vec2 = thin_vec![];
3433-
let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
3434-
assert_eq!(vec, &[(), ()]);
3435-
assert_eq!(t, &[()]);
3436-
}
3615+
#[test]
3616+
fn test_splice_items_zero_sized() {
3617+
let mut vec = thin_vec![(), (), ()];
3618+
let vec2 = thin_vec![];
3619+
let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
3620+
assert_eq!(vec, &[(), ()]);
3621+
assert_eq!(t, &[()]);
3622+
}
34373623

3438-
#[test]
3439-
fn test_splice_unbounded() {
3440-
let mut vec = thin_vec![1, 2, 3, 4, 5];
3441-
let t: ThinVec<_> = vec.splice(.., None).collect();
3442-
assert_eq!(vec, &[]);
3443-
assert_eq!(t, &[1, 2, 3, 4, 5]);
3444-
}
3624+
#[test]
3625+
fn test_splice_unbounded() {
3626+
let mut vec = thin_vec![1, 2, 3, 4, 5];
3627+
let t: ThinVec<_> = vec.splice(.., None).collect();
3628+
assert_eq!(vec, &[]);
3629+
assert_eq!(t, &[1, 2, 3, 4, 5]);
3630+
}
34453631

3446-
#[test]
3447-
fn test_splice_forget() {
3448-
let mut v = thin_vec![1, 2, 3, 4, 5];
3449-
let a = [10, 11, 12];
3450-
::std::mem::forget(v.splice(2..4, a.iter().cloned()));
3451-
assert_eq!(v, &[1, 2]);
3452-
}
3453-
*/
3632+
#[test]
3633+
fn test_splice_forget() {
3634+
let mut v = thin_vec![1, 2, 3, 4, 5];
3635+
let a = [10, 11, 12];
3636+
::std::mem::forget(v.splice(2..4, a.iter().cloned()));
3637+
assert_eq!(v, &[1, 2]);
3638+
}
3639+
3640+
#[test]
3641+
fn test_splice_from_empty() {
3642+
let mut v = thin_vec![];
3643+
let a = [10, 11, 12];
3644+
v.splice(.., a.iter().cloned());
3645+
assert_eq!(v, &[10, 11, 12]);
3646+
}
34543647

34553648
/* probs won't ever impl this
34563649
#[test]

0 commit comments

Comments
 (0)