From 04f65e50cf820faa645cddddbada53b933c53ea9 Mon Sep 17 00:00:00 2001 From: Benjamin Scherer Date: Sat, 18 Jul 2020 00:22:59 -0600 Subject: [PATCH] Add ArrayVec::splice and TinyVec::splice (#85) * Add ArrayVec::splice and TinyVec::splice Added for closer API parity with std::Vec * Fix ArrayVec::splice example typo * Removed FusedIterator bound from splice This bound could've caused confusing error messages, and was inconsistent with the Vec API. splice now uses fuse itself to ensure consistency. Vec::splice consumes the whole iterator at once, so it essentially has the same behavior, but this implementation gradually consumes the iterator as elements are drained, so this fuse is necessary to keep the behavior the same. * Reserve additional capacity in TinyVecSplice Used TinyVec::reserve to pre-allocate space for elements being spliced into the TinyVec after the splicing iterator is dropped. Used the lower bound like Vec's splice does. * Run rustfmt --- src/arrayvec.rs | 190 +++++++++++++++++++++++++++++++++++++-- src/tinyvec.rs | 220 +++++++++++++++++++++++++++++++++++++++++----- tests/arrayvec.rs | 166 ++++++++++++++++++++++++++++++++++ tests/tinyvec.rs | 169 ++++++++++++++++++++++++++++++++++- 4 files changed, 714 insertions(+), 31 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 3527669..b039a0d 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -147,9 +147,11 @@ impl ArrayVec { #[inline] pub fn append(&mut self, other: &mut Self) { let new_len = self.len() + other.len(); - assert!(new_len <= A::CAPACITY, - "ArrayVec::append> total length {} exceeds capacity {}!", - new_len, A::CAPACITY + assert!( + new_len <= A::CAPACITY, + "ArrayVec::append> total length {} exceeds capacity {}!", + new_len, + A::CAPACITY ); for item in other.drain(..) { @@ -174,7 +176,10 @@ impl ArrayVec { /// assert_eq!(av3, &[7, 8, 9][..]); /// ``` #[inline] - pub fn try_append<'other>(&mut self, other: &'other mut Self) -> Option<&'other mut Self> { + pub fn try_append<'other>( + &mut self, + other: &'other mut Self, + ) -> Option<&'other mut Self> { let new_len = self.len() + other.len(); if new_len > A::CAPACITY { return Some(other); @@ -403,8 +408,8 @@ impl ArrayVec { assert!(x.is_none(), "ArrayVec::insert> capacity overflow!"); } - /// Tries to insert an item at the position given, moving all following elements +1 - /// index. + /// Tries to insert an item at the position given, moving all following + /// elements +1 index. /// Returns back the element if the capacity is exhausted, /// otherwise returns None. /// @@ -730,6 +735,74 @@ impl ArrayVec { new } + /// Creates a splicing iterator that removes the specified range in the + /// vector, yields the removed items, and replaces them with elements from + /// the provided iterator. + /// + /// `splice` fuses the provided iterator, so elements after the first `None` + /// are ignored. + /// + /// ## Panics + /// * If the start is greater than the end. + /// * If the end is past the edge of the vec. + /// * If the provided iterator panics. + /// * If the new length would overflow the capacity of the array. Because + /// `ArrayVecSplice` adds elements to this vec in its destructor when + /// necessary, this panic would occur when it is dropped. + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut av = array_vec!([i32; 4] => 1, 2, 3); + /// let av2: ArrayVec<[i32; 4]> = av.splice(1.., 4..=6).collect(); + /// assert_eq!(av.as_slice(), &[1, 4, 5, 6][..]); + /// assert_eq!(av2.as_slice(), &[2, 3][..]); + /// + /// av.splice(.., None); + /// assert_eq!(av.as_slice(), &[]); + /// ``` + #[inline] + pub fn splice( + &mut self, + range: R, + replacement: I, + ) -> ArrayVecSplice<'_, A, core::iter::Fuse> + where + R: RangeBounds, + I: IntoIterator, + { + use core::ops::Bound; + let start = match range.start_bound() { + Bound::Included(x) => *x, + Bound::Excluded(x) => x + 1, + Bound::Unbounded => 0, + }; + let end = match range.end_bound() { + Bound::Included(x) => x + 1, + Bound::Excluded(x) => *x, + Bound::Unbounded => self.len(), + }; + assert!( + start <= end, + "ArrayVec::splice> Illegal range, {} to {}", + start, + end + ); + assert!( + end <= self.len(), + "ArrayVec::splice> Range ends at {} but length is only {}!", + end, + self.len() + ); + + ArrayVecSplice { + removal_start: start, + removal_end: end, + parent: self, + replacement: replacement.into_iter().fuse(), + } + } + /// Remove an element, swapping the end of the vec into its place. /// /// ## Panics @@ -905,6 +978,110 @@ impl<'p, A: Array> Drop for ArrayVecDrain<'p, A> { } } +/// Splicing iterator for `ArrayVec` +/// See [`ArrayVec::splice`](ArrayVec::::splice) +pub struct ArrayVecSplice<'p, A: Array, I: Iterator> { + parent: &'p mut ArrayVec, + removal_start: usize, + removal_end: usize, + replacement: I, +} + +impl<'p, A: Array, I: Iterator> Iterator + for ArrayVecSplice<'p, A, I> +{ + type Item = A::Item; + + fn next(&mut self) -> Option { + if self.removal_start < self.removal_end { + match self.replacement.next() { + Some(replacement) => { + let removed = core::mem::replace( + &mut self.parent[self.removal_start], + replacement, + ); + self.removal_start += 1; + Some(removed) + } + None => { + let removed = self.parent.remove(self.removal_start); + self.removal_end -= 1; + Some(removed) + } + } + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'p, A, I> ExactSizeIterator for ArrayVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ + #[inline] + fn len(&self) -> usize { + self.removal_end - self.removal_start + } +} + +impl<'p, A, I> FusedIterator for ArrayVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ +} + +impl<'p, A, I> DoubleEndedIterator for ArrayVecSplice<'p, A, I> +where + A: Array, + I: Iterator + DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + if self.removal_start < self.removal_end { + match self.replacement.next_back() { + Some(replacement) => { + let removed = core::mem::replace( + &mut self.parent[self.removal_end - 1], + replacement, + ); + self.removal_end -= 1; + Some(removed) + } + None => { + let removed = self.parent.remove(self.removal_end - 1); + self.removal_end -= 1; + Some(removed) + } + } + } else { + None + } + } +} + +impl<'p, A: Array, I: Iterator> Drop + for ArrayVecSplice<'p, A, I> +{ + fn drop(&mut self) { + for _ in self.by_ref() {} + + // FIXME: reserve lower bound of size_hint + + for replacement in self.replacement.by_ref() { + self.parent.insert(self.removal_end, replacement); + self.removal_end += 1; + } + } +} + impl AsMut<[A::Item]> for ArrayVec { #[inline(always)] #[must_use] @@ -1335,4 +1512,3 @@ impl ArrayVec { self.drain_to_vec_and_reserve(0) } } - diff --git a/src/tinyvec.rs b/src/tinyvec.rs index 956a39f..d446c79 100644 --- a/src/tinyvec.rs +++ b/src/tinyvec.rs @@ -161,11 +161,12 @@ impl TinyVec { /// assert!(tv.is_inline()); /// ``` pub fn shrink_to_fit(&mut self) - where A: Default, + where + A: Default, { let vec = match self { TinyVec::Inline(_) => return, - TinyVec::Heap(h) => h, + TinyVec::Heap(h) => h, }; if vec.len() > A::CAPACITY { @@ -191,7 +192,7 @@ impl TinyVec { #[allow(clippy::missing_inline_in_public_items)] pub fn move_to_the_heap(&mut self) { let arr = match self { - TinyVec::Heap(_) => return, + TinyVec::Heap(_) => return, TinyVec::Inline(a) => a, }; @@ -211,10 +212,10 @@ impl TinyVec { /// ``` pub fn move_to_the_heap_and_reserve(&mut self, n: usize) { let arr = match self { - TinyVec::Heap(h) => return h.reserve(n), + TinyVec::Heap(h) => return h.reserve(n), TinyVec::Inline(a) => a, }; - + let v = arr.drain_to_vec_and_reserve(n); *self = TinyVec::Heap(v); } @@ -231,7 +232,7 @@ impl TinyVec { /// ``` pub fn reserve(&mut self, n: usize) { let arr = match self { - TinyVec::Heap(h) => return h.reserve(n), + TinyVec::Heap(h) => return h.reserve(n), TinyVec::Inline(a) => a, }; @@ -250,7 +251,7 @@ impl TinyVec { /// From [Vec::reserve_exact](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve_exact) /// ```text /// Note that the allocator may give the collection more space than it requests. - /// Therefore, capacity can not be relied upon to be precisely minimal. + /// Therefore, capacity can not be relied upon to be precisely minimal. /// Prefer reserve if future insertions are expected. /// ``` /// ```rust @@ -263,7 +264,7 @@ impl TinyVec { /// ``` pub fn reserve_exact(&mut self, n: usize) { let arr = match self { - TinyVec::Heap(h) => return h.reserve_exact(n), + TinyVec::Heap(h) => return h.reserve_exact(n), TinyVec::Inline(a) => a, }; @@ -285,7 +286,7 @@ impl TinyVec { let iter = other.drain(..); match self { - TinyVec::Heap(h) => h.extend(iter), + TinyVec::Heap(h) => h.extend(iter), TinyVec::Inline(a) => a.extend(iter), } } @@ -455,7 +456,7 @@ impl TinyVec { self.reserve(sli.len()); match self { TinyVec::Inline(a) => a.extend_from_slice(sli), - TinyVec::Heap(h) => h.extend_from_slice(sli), + TinyVec::Heap(h) => h.extend_from_slice(sli), } } @@ -505,19 +506,22 @@ impl TinyVec { /// ``` #[inline] pub fn insert(&mut self, index: usize, item: A::Item) { - assert!(index <= self.len(), - "insertion index (is {}) should be <= len (is {})", - index, self.len() + assert!( + index <= self.len(), + "insertion index (is {}) should be <= len (is {})", + index, + self.len() ); let arr = match self { - TinyVec::Heap(v) => return v.insert(index, item), + TinyVec::Heap(v) => return v.insert(index, item), TinyVec::Inline(a) => a, }; if let Some(x) = arr.try_insert(index, item) { let mut v = Vec::with_capacity(arr.len() * 2); - let mut it = arr.iter_mut().map(|r| core::mem::replace(r, Default::default())); + let mut it = + arr.iter_mut().map(|r| core::mem::replace(r, Default::default())); v.extend(it.by_ref().take(index)); v.push(x); v.extend(it); @@ -576,7 +580,7 @@ impl TinyVec { #[inline(always)] pub fn push(&mut self, val: A::Item) { let arr = match self { - TinyVec::Heap(v) => return v.push(val), + TinyVec::Heap(v) => return v.push(val), TinyVec::Inline(a) => a, }; @@ -663,13 +667,13 @@ impl TinyVec { #[inline] pub fn resize_with A::Item>(&mut self, new_len: usize, f: F) { match new_len.checked_sub(self.len()) { - None => return self.truncate(new_len), + None => return self.truncate(new_len), Some(n) => self.reserve(n), } match self { TinyVec::Inline(a) => a.resize_with(new_len, f), - TinyVec::Heap(v) => v.resize_with(new_len, f), + TinyVec::Heap(v) => v.resize_with(new_len, f), } } @@ -720,6 +724,71 @@ impl TinyVec { } } + /// Creates a splicing iterator that removes the specified range in the + /// vector, yields the removed items, and replaces them with elements from + /// the provided iterator. + /// + /// `splice` fuses the provided iterator, so elements after the first `None` + /// are ignored. + /// + /// ## Panics + /// * If the start is greater than the end. + /// * If the end is past the edge of the vec. + /// * If the provided iterator panics. + /// + /// ## Example + /// ```rust + /// use tinyvec::*; + /// let mut tv = tiny_vec!([i32; 4] => 1, 2, 3); + /// let tv2: TinyVec<[i32; 4]> = tv.splice(1.., 4..=6).collect(); + /// assert_eq!(tv.as_slice(), &[1, 4, 5, 6][..]); + /// assert_eq!(tv2.as_slice(), &[2, 3][..]); + /// + /// tv.splice(.., None); + /// assert_eq!(tv.as_slice(), &[]); + /// ``` + #[inline] + pub fn splice( + &mut self, + range: R, + replacement: I, + ) -> TinyVecSplice<'_, A, core::iter::Fuse> + where + R: RangeBounds, + I: IntoIterator, + { + use core::ops::Bound; + let start = match range.start_bound() { + Bound::Included(x) => *x, + Bound::Excluded(x) => x + 1, + Bound::Unbounded => 0, + }; + let end = match range.end_bound() { + Bound::Included(x) => x + 1, + Bound::Excluded(x) => *x, + Bound::Unbounded => self.len(), + }; + assert!( + start <= end, + "TinyVec::splice> Illegal range, {} to {}", + start, + end + ); + assert!( + end <= self.len(), + "TinyVec::splice> Range ends at {} but length is only {}!", + end, + self.len() + ); + + TinyVecSplice { + removal_start: start, + removal_end: end, + parent: self, + replacement: replacement.into_iter().fuse(), + } + } + /// Remove an element, swapping the end of the vec into its place. /// /// ## Panics @@ -800,6 +869,113 @@ impl<'p, A: Array> Drop for TinyVecDrain<'p, A> { } } +/// Splicing iterator for `TinyVec` +/// See [`TinyVec::splice`](TinyVec::::splice) +pub struct TinyVecSplice<'p, A: Array, I: Iterator> { + parent: &'p mut TinyVec, + removal_start: usize, + removal_end: usize, + replacement: I, +} + +impl<'p, A, I> Iterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ + type Item = A::Item; + + fn next(&mut self) -> Option { + if self.removal_start < self.removal_end { + match self.replacement.next() { + Some(replacement) => { + let removed = core::mem::replace( + &mut self.parent[self.removal_start], + replacement, + ); + self.removal_start += 1; + Some(removed) + } + None => { + let removed = self.parent.remove(self.removal_start); + self.removal_end -= 1; + Some(removed) + } + } + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'p, A, I> ExactSizeIterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ + #[inline] + fn len(&self) -> usize { + self.removal_end - self.removal_start + } +} + +impl<'p, A, I> FusedIterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator, +{ +} + +impl<'p, A, I> DoubleEndedIterator for TinyVecSplice<'p, A, I> +where + A: Array, + I: Iterator + DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + if self.removal_start < self.removal_end { + match self.replacement.next_back() { + Some(replacement) => { + let removed = core::mem::replace( + &mut self.parent[self.removal_end - 1], + replacement, + ); + self.removal_end -= 1; + Some(removed) + } + None => { + let removed = self.parent.remove(self.removal_end - 1); + self.removal_end -= 1; + Some(removed) + } + } + } else { + None + } + } +} + +impl<'p, A: Array, I: Iterator> Drop + for TinyVecSplice<'p, A, I> +{ + fn drop(&mut self) { + for _ in self.by_ref() {} + + let (lower_bound, _) = self.replacement.size_hint(); + self.parent.reserve(lower_bound); + + for replacement in self.replacement.by_ref() { + self.parent.insert(self.removal_end, replacement); + self.removal_end += 1; + } + } +} + impl AsMut<[A::Item]> for TinyVec { #[inline(always)] #[must_use] @@ -839,19 +1015,19 @@ impl Extend for TinyVec { let (lower_bound, _) = iter.size_hint(); self.reserve(lower_bound); - let a = match self { + let a = match self { TinyVec::Heap(h) => return h.extend(iter), TinyVec::Inline(a) => a, }; - + let mut iter = a.fill(iter); let maybe = iter.next(); - + let surely = match maybe { Some(x) => x, None => return, }; - + let mut v = a.drain_to_vec_and_reserve(a.len()); v.push(surely); v.extend(iter); diff --git a/tests/arrayvec.rs b/tests/arrayvec.rs index d8c9690..490fd96 100644 --- a/tests/arrayvec.rs +++ b/tests/arrayvec.rs @@ -184,3 +184,169 @@ fn ArrayVec_drain() { assert_eq!(Vec::from_iter(av.clone().drain(1..=1)), vec![2]); assert_eq!(Vec::from_iter(av.clone().drain(1..=2)), vec![2, 3]); } + +#[test] +fn ArrayVec_splice() { + let mut av: ArrayVec<[i32; 10]> = Default::default(); + av.push(1); + av.push(2); + av.push(3); + + // splice returns the same things as drain + assert_eq!(Vec::from_iter(av.clone().splice(.., None)), vec![1, 2, 3]); + + assert_eq!(Vec::from_iter(av.clone().splice(..2, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(av.clone().splice(..3, None)), vec![1, 2, 3]); + + assert_eq!(Vec::from_iter(av.clone().splice(..=1, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(av.clone().splice(..=2, None)), vec![1, 2, 3]); + + assert_eq!(Vec::from_iter(av.clone().splice(0.., None)), vec![1, 2, 3]); + assert_eq!(Vec::from_iter(av.clone().splice(1.., None)), vec![2, 3]); + + assert_eq!(Vec::from_iter(av.clone().splice(0..2, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(av.clone().splice(0..3, None)), vec![1, 2, 3]); + assert_eq!(Vec::from_iter(av.clone().splice(1..2, None)), vec![2]); + assert_eq!(Vec::from_iter(av.clone().splice(1..3, None)), vec![2, 3]); + + assert_eq!(Vec::from_iter(av.clone().splice(0..=1, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(av.clone().splice(0..=2, None)), vec![1, 2, 3]); + assert_eq!(Vec::from_iter(av.clone().splice(1..=1, None)), vec![2]); + assert_eq!(Vec::from_iter(av.clone().splice(1..=2, None)), vec![2, 3]); + + // splice removes the same things as drain + let mut av2 = av.clone(); + av2.splice(.., None); + assert_eq!(av2, array_vec![]); + + let mut av2 = av.clone(); + av2.splice(..2, None); + assert_eq!(av2, array_vec![3]); + + let mut av2 = av.clone(); + av2.splice(..3, None); + assert_eq!(av2, array_vec![]); + + let mut av2 = av.clone(); + av2.splice(..=1, None); + assert_eq!(av2, array_vec![3]); + let mut av2 = av.clone(); + av2.splice(..=2, None); + assert_eq!(av2, array_vec![]); + + let mut av2 = av.clone(); + av2.splice(0.., None); + assert_eq!(av2, array_vec![]); + let mut av2 = av.clone(); + av2.splice(1.., None); + assert_eq!(av2, array_vec![1]); + + let mut av2 = av.clone(); + av2.splice(0..2, None); + assert_eq!(av2, array_vec![3]); + + let mut av2 = av.clone(); + av2.splice(0..3, None); + assert_eq!(av2, array_vec![]); + let mut av2 = av.clone(); + av2.splice(1..2, None); + assert_eq!(av2, array_vec![1, 3]); + + let mut av2 = av.clone(); + av2.splice(1..3, None); + assert_eq!(av2, array_vec![1]); + + let mut av2 = av.clone(); + av2.splice(0..=1, None); + assert_eq!(av2, array_vec![3]); + + let mut av2 = av.clone(); + av2.splice(0..=2, None); + assert_eq!(av2, array_vec![]); + + let mut av2 = av.clone(); + av2.splice(1..=1, None); + assert_eq!(av2, array_vec![1, 3]); + + let mut av2 = av.clone(); + av2.splice(1..=2, None); + assert_eq!(av2, array_vec![1]); + + // splice adds the elements correctly + let mut av2 = av.clone(); + av2.splice(.., 4..=6); + assert_eq!(av2, array_vec![4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(..2, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6, 3]); + + let mut av2 = av.clone(); + av2.splice(..3, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(..=1, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6, 3]); + + let mut av2 = av.clone(); + av2.splice(..=2, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(0.., 4..=6); + assert_eq!(av2, array_vec![4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(1.., 4..=6); + assert_eq!(av2, array_vec![1, 4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(0..2, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6, 3]); + + let mut av2 = av.clone(); + av2.splice(0..3, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(1..2, 4..=6); + assert_eq!(av2, array_vec![1, 4, 5, 6, 3]); + + let mut av2 = av.clone(); + av2.splice(1..3, 4..=6); + assert_eq!(av2, array_vec![1, 4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(0..=1, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6, 3]); + + let mut av2 = av.clone(); + av2.splice(0..=2, 4..=6); + assert_eq!(av2, array_vec![4, 5, 6]); + + let mut av2 = av.clone(); + av2.splice(1..=1, 4..=6); + assert_eq!(av2, array_vec![1, 4, 5, 6, 3]); + + let mut av2 = av.clone(); + av2.splice(1..=2, 4..=6); + assert_eq!(av2, array_vec![1, 4, 5, 6]); + + // splice adds the elements correctly when the replacement is smaller + let mut av2 = av.clone(); + av2.splice(.., Some(4)); + assert_eq!(av2, array_vec![4]); + + let mut av2 = av.clone(); + av2.splice(..2, Some(4)); + assert_eq!(av2, array_vec![4, 3]); + + let mut av2 = av.clone(); + av2.splice(1.., Some(4)); + assert_eq!(av2, array_vec![1, 4]); + + let mut av2 = av.clone(); + av2.splice(1..=1, Some(4)); + assert_eq!(av2, array_vec![1, 4, 3]); +} diff --git a/tests/tinyvec.rs b/tests/tinyvec.rs index 8f48798..9a2b485 100644 --- a/tests/tinyvec.rs +++ b/tests/tinyvec.rs @@ -60,6 +60,172 @@ fn TinyVec_drain() { assert_eq!(Vec::from_iter(tv.clone().drain(1..=2)), vec![2, 3]); } +#[test] +fn TinyVec_splice() { + let mut tv: TinyVec<[i32; 10]> = Default::default(); + tv.push(1); + tv.push(2); + tv.push(3); + + // splice returns the same things as drain + assert_eq!(Vec::from_iter(tv.clone().splice(.., None)), vec![1, 2, 3]); + + assert_eq!(Vec::from_iter(tv.clone().splice(..2, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(tv.clone().splice(..3, None)), vec![1, 2, 3]); + + assert_eq!(Vec::from_iter(tv.clone().splice(..=1, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(tv.clone().splice(..=2, None)), vec![1, 2, 3]); + + assert_eq!(Vec::from_iter(tv.clone().splice(0.., None)), vec![1, 2, 3]); + assert_eq!(Vec::from_iter(tv.clone().splice(1.., None)), vec![2, 3]); + + assert_eq!(Vec::from_iter(tv.clone().splice(0..2, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(tv.clone().splice(0..3, None)), vec![1, 2, 3]); + assert_eq!(Vec::from_iter(tv.clone().splice(1..2, None)), vec![2]); + assert_eq!(Vec::from_iter(tv.clone().splice(1..3, None)), vec![2, 3]); + + assert_eq!(Vec::from_iter(tv.clone().splice(0..=1, None)), vec![1, 2]); + assert_eq!(Vec::from_iter(tv.clone().splice(0..=2, None)), vec![1, 2, 3]); + assert_eq!(Vec::from_iter(tv.clone().splice(1..=1, None)), vec![2]); + assert_eq!(Vec::from_iter(tv.clone().splice(1..=2, None)), vec![2, 3]); + + // splice removes the same things as drain + let mut tv2 = tv.clone(); + tv2.splice(.., None); + assert_eq!(tv2, tiny_vec![]); + + let mut tv2 = tv.clone(); + tv2.splice(..2, None); + assert_eq!(tv2, tiny_vec![3]); + + let mut tv2 = tv.clone(); + tv2.splice(..3, None); + assert_eq!(tv2, tiny_vec![]); + + let mut tv2 = tv.clone(); + tv2.splice(..=1, None); + assert_eq!(tv2, tiny_vec![3]); + let mut tv2 = tv.clone(); + tv2.splice(..=2, None); + assert_eq!(tv2, tiny_vec![]); + + let mut tv2 = tv.clone(); + tv2.splice(0.., None); + assert_eq!(tv2, tiny_vec![]); + let mut tv2 = tv.clone(); + tv2.splice(1.., None); + assert_eq!(tv2, tiny_vec![1]); + + let mut tv2 = tv.clone(); + tv2.splice(0..2, None); + assert_eq!(tv2, tiny_vec![3]); + + let mut tv2 = tv.clone(); + tv2.splice(0..3, None); + assert_eq!(tv2, tiny_vec![]); + let mut tv2 = tv.clone(); + tv2.splice(1..2, None); + assert_eq!(tv2, tiny_vec![1, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(1..3, None); + assert_eq!(tv2, tiny_vec![1]); + + let mut tv2 = tv.clone(); + tv2.splice(0..=1, None); + assert_eq!(tv2, tiny_vec![3]); + + let mut tv2 = tv.clone(); + tv2.splice(0..=2, None); + assert_eq!(tv2, tiny_vec![]); + + let mut tv2 = tv.clone(); + tv2.splice(1..=1, None); + assert_eq!(tv2, tiny_vec![1, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(1..=2, None); + assert_eq!(tv2, tiny_vec![1]); + + // splice adds the elements correctly + let mut tv2 = tv.clone(); + tv2.splice(.., 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(..2, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(..3, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(..=1, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(..=2, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(0.., 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(1.., 4..=6); + assert_eq!(tv2, tiny_vec![1, 4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(0..2, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(0..3, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(1..2, 4..=6); + assert_eq!(tv2, tiny_vec![1, 4, 5, 6, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(1..3, 4..=6); + assert_eq!(tv2, tiny_vec![1, 4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(0..=1, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(0..=2, 4..=6); + assert_eq!(tv2, tiny_vec![4, 5, 6]); + + let mut tv2 = tv.clone(); + tv2.splice(1..=1, 4..=6); + assert_eq!(tv2, tiny_vec![1, 4, 5, 6, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(1..=2, 4..=6); + assert_eq!(tv2, tiny_vec![1, 4, 5, 6]); + + // splice adds the elements correctly when the replacement is smaller + let mut tv2 = tv.clone(); + tv2.splice(.., Some(4)); + assert_eq!(tv2, tiny_vec![4]); + + let mut tv2 = tv.clone(); + tv2.splice(..2, Some(4)); + assert_eq!(tv2, tiny_vec![4, 3]); + + let mut tv2 = tv.clone(); + tv2.splice(1.., Some(4)); + assert_eq!(tv2, tiny_vec![1, 4]); + + let mut tv2 = tv.clone(); + tv2.splice(1..=1, Some(4)); + assert_eq!(tv2, tiny_vec![1, 4, 3]); +} + #[test] fn TinyVec_resize() { let mut tv: TinyVec<[i32; 10]> = Default::default(); @@ -149,6 +315,5 @@ fn TinyVec_move_to_heap_and_shrink() { assert_eq!(tv.capacity(), 4); tv.extend(2..=4); assert_eq!(tv.capacity(), 4); - assert_eq!(tv.as_slice(), [1,2,3,4]); + assert_eq!(tv.as_slice(), [1, 2, 3, 4]); } -