From a290c37e69530b11a02746db155443218fc27a6a Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 19 Feb 2024 14:28:50 -0600 Subject: [PATCH] Relax From for SmallVec to allow different length arrays. --- src/lib.rs | 22 +++++++++++++++++++--- src/tests.rs | 10 ++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d25f868..c94db53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1909,9 +1909,25 @@ impl<'a, T: Clone, const N: usize> From<&'a [T]> for SmallVec { slice.iter().cloned().collect() } } -impl From<[T; N]> for SmallVec { - fn from(array: [T; N]) -> Self { - Self::from_buf(array) + +impl From<[T; M]> for SmallVec { + fn from(array: [T; M]) -> Self { + if M > N { + // If M > N, we'd have to heap allocate anyway, + // so delegate for Vec for the allocation + Self::from(Vec::from(array)) + } else { + // M <= N + let mut this = Self::new(); + debug_assert!(M <= this.capacity()); + let array = ManuallyDrop::new(array); + // SAFETY: M <= this.capacity() + unsafe { + copy_nonoverlapping(array.as_ptr(), this.as_mut_ptr(), M); + this.set_len(M); + } + this + } } } impl From> for SmallVec { diff --git a/src/tests.rs b/src/tests.rs index b77ea05..b1a4f45 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -656,6 +656,16 @@ fn test_from() { let small_vec: SmallVec = SmallVec::from(vec); assert_eq!(&*small_vec, &[NoClone(42)]); drop(small_vec); + + let array = [1; 128]; + let small_vec: SmallVec = SmallVec::from(array); + assert_eq!(&*small_vec, vec![1; 128].as_slice()); + drop(small_vec); + + let array = [99]; + let small_vec: SmallVec = SmallVec::from(array); + assert_eq!(&*small_vec, &[99u8]); + drop(small_vec); } #[test]