mirror of
https://github.com/Lokathor/bytemuck.git
synced 2024-11-25 16:22:56 +00:00
Add a method to allocate zeroed slices
Note that the method requires a Pod and not only a Zeroable structure since only the latter guarantees that slices have a consistent layout. We need to compute this layout to manually allocate it.
This commit is contained in:
parent
da1ba1ec80
commit
11e791c88a
@ -72,6 +72,44 @@ pub fn zeroed_box<T: Zeroable>() -> Box<T> {
|
|||||||
try_zeroed_box().unwrap()
|
try_zeroed_box().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allocates a `Box<[T]>` with all contents being zeroed out.
|
||||||
|
///
|
||||||
|
/// This uses the global allocator to create a zeroed allocation and _then_
|
||||||
|
/// turns it into a Box. In other words, it's 100% assured that the zeroed data
|
||||||
|
/// won't be put temporarily on the stack. You can make a box of any size
|
||||||
|
/// without fear of a stack overflow.
|
||||||
|
///
|
||||||
|
/// ## Failure
|
||||||
|
///
|
||||||
|
/// This fails if the allocation fails.
|
||||||
|
#[inline]
|
||||||
|
pub fn try_zeroed_slice_box<T: Pod>(length: usize) -> Result<Box<[T]>, ()> {
|
||||||
|
if size_of::<T>() == 0 {
|
||||||
|
// This will not allocate but simple create a dangling slice pointer.
|
||||||
|
let mut vec = Vec::with_capacity(length);
|
||||||
|
vec.resize(length, T::zeroed());
|
||||||
|
return Ok(vec.into_boxed_slice());
|
||||||
|
}
|
||||||
|
if length == 0 {
|
||||||
|
// This will also not allocate.
|
||||||
|
return Ok(Vec::new().into_boxed_slice());
|
||||||
|
}
|
||||||
|
// For Pod types, the layout of the array/slice is equivalent to repeating the type.
|
||||||
|
let layout_length = size_of::<T>().checked_mul(length).ok_or(())?;
|
||||||
|
assert!(layout_length != 0);
|
||||||
|
let layout =
|
||||||
|
Layout::from_size_align(layout_length, align_of::<T>()).map_err(|_| ())?;
|
||||||
|
let ptr = unsafe { alloc_zeroed(layout) };
|
||||||
|
if ptr.is_null() {
|
||||||
|
// we don't know what the error is because `alloc_zeroed` is a dumb API
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
let slice =
|
||||||
|
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
|
||||||
|
Ok(unsafe { Box::<[T]>::from_raw(slice) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// As [`try_cast_vec`](try_cast_vec), but unwraps for you.
|
/// As [`try_cast_vec`](try_cast_vec), but unwraps for you.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cast_vec<A: Pod, B: Pod>(input: Vec<A>) -> Vec<B> {
|
pub fn cast_vec<A: Pod, B: Pod>(input: Vec<A>) -> Vec<B> {
|
||||||
|
Loading…
Reference in New Issue
Block a user