From 5ece63ce763acec5e3f8c691ef0575517ae331fc Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 10 Dec 2024 21:28:28 +0100 Subject: [PATCH] Implement spare_capacity_mut Mirrors the implementation from `Vec::spare_capacity_mut`. This is useful to write directly into the buffer after `SmallVec::with_capacity`, removing the overhead of the `SmallVec` model entirely when doing so. --- src/lib.rs | 16 ++++++++++++++++ src/tests.rs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 803e50e..1fbdc7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1413,6 +1413,22 @@ impl<T, const N: usize> SmallVec<T, N> { } } + /// Returns the remaining spare capacity of the vector as a slice of + /// `MaybeUninit<T>`. + /// + /// The returned slice can be used to fill the vector with data (e.g. by + /// reading from a file) before marking the data as initialized using the + /// [`set_len`](Self::set_len) method. + #[inline] + pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] { + unsafe { + core::slice::from_raw_parts_mut( + self.as_mut_ptr().add(self.len()) as *mut MaybeUninit<T>, + self.capacity() - self.len(), + ) + } + } + /// Creates a `SmallVec` directly from the raw components of another `SmallVec`. /// /// # Safety diff --git a/src/tests.rs b/src/tests.rs index 3186fb5..2f0a1f2 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1136,7 +1136,9 @@ fn collect_from_iter() { impl<I: Iterator> Iterator for IterNoHint<I> { type Item = I::Item; - fn next(&mut self) -> Option<Self::Item> { self.0.next() } + fn next(&mut self) -> Option<Self::Item> { + self.0.next() + } // no implementation of size_hint means it returns (0, None) - which forces from_iter to // grow the allocated space iteratively. @@ -1148,3 +1150,30 @@ fn collect_from_iter() { let _y: SmallVec<u8, 1> = SmallVec::from_iter(iter); } + +#[test] +fn test_spare_capacity_mut() { + let mut v: SmallVec<u8, 2> = SmallVec::new(); + assert!(!v.spilled()); + let spare = v.spare_capacity_mut(); + assert_eq!(spare.len(), 2); + assert_eq!(spare.as_ptr().cast::<u8>(), v.as_ptr()); + + v.push(1); + assert!(!v.spilled()); + let spare = v.spare_capacity_mut(); + assert_eq!(spare.len(), 1); + assert_eq!(spare.as_ptr().cast::<u8>(), unsafe { v.as_ptr().add(1) }); + + v.push(2); + assert!(!v.spilled()); + let spare = v.spare_capacity_mut(); + assert_eq!(spare.len(), 0); + assert_eq!(spare.as_ptr().cast::<u8>(), unsafe { v.as_ptr().add(2) }); + + v.push(3); + assert!(v.spilled()); + let spare = v.spare_capacity_mut(); + assert!(spare.len() >= 1); + assert_eq!(spare.as_ptr().cast::<u8>(), unsafe { v.as_ptr().add(3) }); +}