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>14pub(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>28pub(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