diff options
Diffstat (limited to 'src/misc.rs')
-rw-r--r-- | src/misc.rs | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/src/misc.rs b/src/misc.rs index d923d58..faef34f 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,37 +1,52 @@ use std::mem; +use std::mem::MaybeUninit; use std::slice; -/// Slice from `vec[vec.len()..vec.capacity()]` -pub unsafe fn remaining_capacity_as_slice_mut<A>(vec: &mut Vec<A>) -> &mut [A] { - slice::from_raw_parts_mut( - vec.as_mut_slice().as_mut_ptr().offset(vec.len() as isize), - vec.capacity() - vec.len(), - ) +/// `Vec::spare_capacity_mut` is not stable until Rust 1.60. +pub(crate) fn vec_spare_capacity_mut<A>(vec: &mut Vec<A>) -> &mut [MaybeUninit<A>] { + // SAFETY: copy-paste from rust stdlib. + unsafe { + slice::from_raw_parts_mut( + vec.as_mut_ptr().add(vec.len()) as *mut MaybeUninit<A>, + vec.capacity() - vec.len(), + ) + } } -pub unsafe fn remove_lifetime_mut<A: ?Sized>(a: &mut A) -> &'static mut A { - mem::transmute(a) +/// `MaybeUninit::write_slice` is not stable. +pub(crate) fn maybe_uninit_write_slice<'a, T>( + this: &'a mut [MaybeUninit<T>], + src: &[T], +) -> &'a mut [T] +where + T: Copy, +{ + // SAFETY: copy-paste from rust stdlib. + + let uninit_src: &[MaybeUninit<T>] = unsafe { mem::transmute(src) }; + + this.copy_from_slice(uninit_src); + + unsafe { &mut *(this as *mut [MaybeUninit<T>] as *mut [T]) } } -#[cfg(test)] -mod test { - use super::*; +/// `MaybeUninit::array_assume_init` is not stable. +#[inline] +pub(crate) unsafe fn maybe_ununit_array_assume_init<T, const N: usize>( + array: [MaybeUninit<T>; N], +) -> [T; N] { + // SAFETY: + // * The caller guarantees that all elements of the array are initialized + // * `MaybeUninit<T>` and T are guaranteed to have the same layout + // * `MaybeUninit` does not drop, so there are no double-frees + // And thus the conversion is safe + (&array as *const _ as *const [T; N]).read() +} - #[test] - fn test_remaining_capacity_as_slice_mut() { - let mut v = Vec::with_capacity(5); - v.push(10); - v.push(11); - v.push(12); - unsafe { - { - let s = remaining_capacity_as_slice_mut(&mut v); - assert_eq!(2, s.len()); - s[0] = 13; - s[1] = 14; - } - v.set_len(5); - } - assert_eq!(vec![10, 11, 12, 13, 14], v); - } +/// `MaybeUninit::write` is stable since 1.55. +#[inline] +pub(crate) fn maybe_uninit_write<T>(uninit: &mut MaybeUninit<T>, val: T) -> &mut T { + // SAFETY: copy-paste from rust stdlib. + *uninit = MaybeUninit::new(val); + unsafe { &mut *uninit.as_mut_ptr() } } |