From f2f584a084f8cc53e1750921c271cc4a81e900ac Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 11 Apr 2023 19:50:35 +0000 Subject: [PATCH] Add `push_many_from_slice` method See docs for details. --- src/arrayvec.rs | 29 +++++++++++++++++++++++++++++ tests/tests.rs | 17 ++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index a21bbb3..875b65c 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -579,6 +579,35 @@ impl ArrayVec { Ok(()) } + /// Copy as many elements as we can from the slice and append to the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut vec: ArrayVec = ArrayVec::new(); + /// vec.push(1); + /// let rest = vec.push_many_from_slice(&[2, 3]); + /// assert_eq!(&vec[..], &[1, 2]); + /// assert_eq!(rest, &[3]); + /// ``` + /// + /// Can be thought of as a variation of [try_extend_from_slice] where + /// instead of failing, it does the "best it can" (extends the `ArrayVec` + /// with some but not all of the elements). + pub fn push_many_from_slice<'a, 'b>(&'a mut self, other: &'b [T]) -> &'b [T] + where T: Copy, + { + let self_len = self.len(); + let take = usize::min(self.remaining_capacity(), other.len()); + + unsafe { + let dst = self.get_unchecked_ptr(self_len); + ptr::copy_nonoverlapping(other.as_ptr(), dst, take); + self.set_len(self_len + take); + } + &other[take..] + } + /// Create a draining iterator that removes the specified range in the vector /// and yields the removed items from start to end. The element range is /// removed even if the iterator is not consumed until the end. diff --git a/tests/tests.rs b/tests/tests.rs index 2f8a5ef..90e171a 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -74,6 +74,21 @@ fn test_try_from_slice_error() { assert_matches!(res, Err(_)); } +#[test] +fn test_push_many_from_slice() { + let mut vec: ArrayVec = ArrayVec::new(); + + let ret = vec.push_many_from_slice(&[1, 2, 3]); + assert_eq!(ret, &[]); + assert_eq!(vec.len(), 3); + assert_eq!(&vec[..], &[1, 2, 3]); + assert_eq!(vec.pop(), Some(3)); + assert_eq!(&vec[..], &[1, 2]); + let ret = vec.push_many_from_slice(&[3, 4, 5, 6]); + assert_eq!(&vec[..], &[1, 2, 3, 4]); + assert_eq!(ret, &[5, 6]); +} + #[test] fn test_u16_index() { const N: usize = 4096; @@ -790,4 +805,4 @@ fn test_arraystring_zero_filled_has_some_sanity_checks() { let string = ArrayString::<4>::zero_filled(); assert_eq!(string.as_str(), "\0\0\0\0"); assert_eq!(string.len(), 4); -} \ No newline at end of file +}