Skip to content

Commit 6ba116c

Browse files
authored
reimplement from_buf (#377)
1 parent 395763c commit 6ba116c

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

src/lib.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -673,11 +673,27 @@ impl<T, const N: usize> SmallVec<T, N> {
673673
}
674674

675675
#[inline]
676-
pub const fn from_buf(buf: [T; N]) -> Self {
677-
// SAFETY: all the members in 0..N are initialized
676+
pub const fn from_buf<const S: usize>(elements: [T; S]) -> Self {
677+
assert!(S <= N); // Free check since the values are known at compile time
678+
679+
// Althought we create a new buffer, since S and N are known at compile time,
680+
// even with `-C opt-level=1`, it gets optimized as best as it could be. (Checked with <godbolt.org>)
681+
let mut buf: MaybeUninit<[T; N]> = MaybeUninit::uninit();
682+
683+
// SAFETY: buf and elements do not overlap, are aligned and have space
684+
// for at least S elements since S <= N.
685+
// We will drop the elements only once since we do forget(elements).
686+
unsafe {
687+
copy_nonoverlapping(elements.as_ptr(), buf.as_mut_ptr() as *mut T, S);
688+
}
689+
690+
// `elements` have been moved into buf and will be droped by SmallVec
691+
core::mem::forget(elements);
692+
693+
// SAFETY: all the members in 0..S are initialized
678694
Self {
679-
len: TaggedLen::new(N, false, Self::is_zst()),
680-
raw: RawSmallVec::new_inline(MaybeUninit::new(buf)),
695+
len: TaggedLen::new(S, false, Self::is_zst()),
696+
raw: RawSmallVec::new_inline(buf),
681697
_marker: PhantomData,
682698
}
683699
}

0 commit comments

Comments
 (0)