xref: /wasmtime-44.0.1/crates/core/src/error/boxed.rs (revision 8325e1ec)
1 use super::{OutOfMemory, Result};
2 use core::alloc::Layout;
3 use core::mem::MaybeUninit;
4 use core::ptr::NonNull;
5 use std_alloc::boxed::Box;
6 
7 /// Try to allocate a block of memory that fits the given layout, or return an
8 /// `OutOfMemory` error.
9 ///
10 /// # Safety
11 ///
12 /// Same as `alloc::alloc::alloc`: layout must have non-zero size.
13 #[inline]
try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory>14 pub(crate) unsafe fn try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {
15     // Safety: same as our safety conditions.
16     debug_assert!(layout.size() > 0);
17     let ptr = unsafe { std_alloc::alloc::alloc(layout) };
18 
19     if let Some(ptr) = NonNull::new(ptr) {
20         Ok(ptr)
21     } else {
22         Err(OutOfMemory::new(layout.size()))
23     }
24 }
25 
26 /// Create a `Box<T>`, or return an `OutOfMemory` error.
27 #[inline]
try_new_uninit_box<T>() -> Result<Box<MaybeUninit<T>>, OutOfMemory>28 pub(crate) fn try_new_uninit_box<T>() -> Result<Box<MaybeUninit<T>>, OutOfMemory> {
29     let layout = std_alloc::alloc::Layout::new::<MaybeUninit<T>>();
30 
31     if layout.size() == 0 {
32         // NB: no actual allocation takes place when boxing zero-sized types.
33         return Ok(Box::new(MaybeUninit::uninit()));
34     }
35 
36     // Safety: layout size is non-zero.
37     let ptr = unsafe { try_alloc(layout)? };
38 
39     let ptr = ptr.cast::<MaybeUninit<T>>();
40 
41     // Safety: The pointer's memory block was allocated by the global allocator.
42     Ok(unsafe { Box::from_raw(ptr.as_ptr()) })
43 }
44