Skip to content

Commit 54090ed

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 9e18364 commit 54090ed

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
@@ -1438,6 +1438,53 @@ impl<T> ThinVec<T> {
14381438
}
14391439
}
14401440

1441+
/// Creates a splicing iterator that replaces the specified range in the vector
1442+
/// with the given `replace_with` iterator and yields the removed items.
1443+
/// `replace_with` does not need to be the same length as `range`.
1444+
///
1445+
/// `range` is removed even if the iterator is not consumed until the end.
1446+
///
1447+
/// It is unspecified how many elements are removed from the vector
1448+
/// if the `Splice` value is leaked.
1449+
///
1450+
/// The input iterator `replace_with` is only consumed when the `Splice` value is dropped.
1451+
///
1452+
/// This is optimal if:
1453+
///
1454+
/// * The tail (elements in the vector after `range`) is empty,
1455+
/// * or `replace_with` yields fewer or equal elements than `range`’s length
1456+
/// * or the lower bound of its `size_hint()` is exact.
1457+
///
1458+
/// Otherwise, a temporary vector is allocated and the tail is moved twice.
1459+
///
1460+
/// # Panics
1461+
///
1462+
/// Panics if the starting point is greater than the end point or if
1463+
/// the end point is greater than the length of the vector.
1464+
///
1465+
/// # Examples
1466+
///
1467+
/// ```
1468+
/// use thin_vec::{ThinVec, thin_vec};
1469+
///
1470+
/// let mut v = thin_vec![1, 2, 3, 4];
1471+
/// let new = [7, 8, 9];
1472+
/// let u: ThinVec<_> = v.splice(1..3, new).collect();
1473+
/// assert_eq!(v, &[1, 7, 8, 9, 4]);
1474+
/// assert_eq!(u, &[2, 3]);
1475+
/// ```
1476+
#[inline]
1477+
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
1478+
where
1479+
R: RangeBounds<usize>,
1480+
I: IntoIterator<Item = T>,
1481+
{
1482+
Splice {
1483+
drain: self.drain(range),
1484+
replace_with: replace_with.into_iter(),
1485+
}
1486+
}
1487+
14411488
/// Resize the buffer and update its capacity, without changing the length.
14421489
/// Unsafe because it can cause length to be greater than capacity.
14431490
unsafe fn reallocate(&mut self, new_cap: usize) {
@@ -2412,6 +2459,133 @@ impl<'a, T> AsRef<[T]> for Drain<'a, T> {
24122459
}
24132460
}
24142461

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

2825+
{
2826+
let mut v = ThinVec::<i32>::new();
2827+
assert_eq!(v.splice(.., []).len(), 0);
2828+
2829+
for _ in v.splice(.., []) {
2830+
unreachable!()
2831+
}
2832+
2833+
assert_eq!(v.len(), 0);
2834+
assert_eq!(v.capacity(), 0);
2835+
assert_eq!(&v[..], &[]);
2836+
}
2837+
26512838
{
26522839
let mut v = ThinVec::<i32>::new();
26532840
v.truncate(1);
@@ -3402,70 +3589,76 @@ mod std_tests {
34023589
v.drain(5..=5);
34033590
}
34043591

3405-
/* TODO: implement splice?
3406-
#[test]
3407-
fn test_splice() {
3408-
let mut v = thin_vec![1, 2, 3, 4, 5];
3409-
let a = [10, 11, 12];
3410-
v.splice(2..4, a.iter().cloned());
3411-
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3412-
v.splice(1..3, Some(20));
3413-
assert_eq!(v, &[1, 20, 11, 12, 5]);
3414-
}
3592+
#[test]
3593+
fn test_splice() {
3594+
let mut v = thin_vec![1, 2, 3, 4, 5];
3595+
let a = [10, 11, 12];
3596+
v.splice(2..4, a.iter().cloned());
3597+
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3598+
v.splice(1..3, Some(20));
3599+
assert_eq!(v, &[1, 20, 11, 12, 5]);
3600+
}
34153601

3416-
#[test]
3417-
fn test_splice_inclusive_range() {
3418-
let mut v = thin_vec![1, 2, 3, 4, 5];
3419-
let a = [10, 11, 12];
3420-
let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
3421-
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3422-
assert_eq!(t1, &[3, 4]);
3423-
let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
3424-
assert_eq!(v, &[1, 20, 11, 12, 5]);
3425-
assert_eq!(t2, &[2, 10]);
3426-
}
3602+
#[test]
3603+
fn test_splice_inclusive_range() {
3604+
let mut v = thin_vec![1, 2, 3, 4, 5];
3605+
let a = [10, 11, 12];
3606+
let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
3607+
assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
3608+
assert_eq!(t1, &[3, 4]);
3609+
let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
3610+
assert_eq!(v, &[1, 20, 11, 12, 5]);
3611+
assert_eq!(t2, &[2, 10]);
3612+
}
34273613

3428-
#[test]
3429-
#[should_panic]
3430-
fn test_splice_out_of_bounds() {
3431-
let mut v = thin_vec![1, 2, 3, 4, 5];
3432-
let a = [10, 11, 12];
3433-
v.splice(5..6, a.iter().cloned());
3434-
}
3614+
#[test]
3615+
#[should_panic]
3616+
fn test_splice_out_of_bounds() {
3617+
let mut v = thin_vec![1, 2, 3, 4, 5];
3618+
let a = [10, 11, 12];
3619+
v.splice(5..6, a.iter().cloned());
3620+
}
34353621

3436-
#[test]
3437-
#[should_panic]
3438-
fn test_splice_inclusive_out_of_bounds() {
3439-
let mut v = thin_vec![1, 2, 3, 4, 5];
3440-
let a = [10, 11, 12];
3441-
v.splice(5..=5, a.iter().cloned());
3442-
}
3622+
#[test]
3623+
#[should_panic]
3624+
fn test_splice_inclusive_out_of_bounds() {
3625+
let mut v = thin_vec![1, 2, 3, 4, 5];
3626+
let a = [10, 11, 12];
3627+
v.splice(5..=5, a.iter().cloned());
3628+
}
34433629

3444-
#[test]
3445-
fn test_splice_items_zero_sized() {
3446-
let mut vec = thin_vec![(), (), ()];
3447-
let vec2 = thin_vec![];
3448-
let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
3449-
assert_eq!(vec, &[(), ()]);
3450-
assert_eq!(t, &[()]);
3451-
}
3630+
#[test]
3631+
fn test_splice_items_zero_sized() {
3632+
let mut vec = thin_vec![(), (), ()];
3633+
let vec2 = thin_vec![];
3634+
let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
3635+
assert_eq!(vec, &[(), ()]);
3636+
assert_eq!(t, &[()]);
3637+
}
34523638

3453-
#[test]
3454-
fn test_splice_unbounded() {
3455-
let mut vec = thin_vec![1, 2, 3, 4, 5];
3456-
let t: ThinVec<_> = vec.splice(.., None).collect();
3457-
assert_eq!(vec, &[]);
3458-
assert_eq!(t, &[1, 2, 3, 4, 5]);
3459-
}
3639+
#[test]
3640+
fn test_splice_unbounded() {
3641+
let mut vec = thin_vec![1, 2, 3, 4, 5];
3642+
let t: ThinVec<_> = vec.splice(.., None).collect();
3643+
assert_eq!(vec, &[]);
3644+
assert_eq!(t, &[1, 2, 3, 4, 5]);
3645+
}
34603646

3461-
#[test]
3462-
fn test_splice_forget() {
3463-
let mut v = thin_vec![1, 2, 3, 4, 5];
3464-
let a = [10, 11, 12];
3465-
::std::mem::forget(v.splice(2..4, a.iter().cloned()));
3466-
assert_eq!(v, &[1, 2]);
3467-
}
3468-
*/
3647+
#[test]
3648+
fn test_splice_forget() {
3649+
let mut v = thin_vec![1, 2, 3, 4, 5];
3650+
let a = [10, 11, 12];
3651+
::std::mem::forget(v.splice(2..4, a.iter().cloned()));
3652+
assert_eq!(v, &[1, 2]);
3653+
}
3654+
3655+
#[test]
3656+
fn test_splice_from_empty() {
3657+
let mut v = thin_vec![];
3658+
let a = [10, 11, 12];
3659+
v.splice(.., a.iter().cloned());
3660+
assert_eq!(v, &[10, 11, 12]);
3661+
}
34693662

34703663
/* probs won't ever impl this
34713664
#[test]

0 commit comments

Comments
 (0)