use super::{OutOfMemory, Result}; use core::alloc::Layout; use core::mem::MaybeUninit; use core::ptr::NonNull; use std_alloc::boxed::Box; /// Try to allocate a block of memory that fits the given layout, or return an /// `OutOfMemory` error. /// /// # Safety /// /// Same as `alloc::alloc::alloc`: layout must have non-zero size. #[inline] pub(crate) unsafe fn try_alloc(layout: Layout) -> Result, OutOfMemory> { // Safety: same as our safety conditions. debug_assert!(layout.size() > 0); let ptr = unsafe { std_alloc::alloc::alloc(layout) }; if let Some(ptr) = NonNull::new(ptr) { Ok(ptr) } else { Err(OutOfMemory::new(layout.size())) } } /// Create a `Box`, or return an `OutOfMemory` error. #[inline] pub(crate) fn try_new_uninit_box() -> Result>, OutOfMemory> { let layout = std_alloc::alloc::Layout::new::>(); if layout.size() == 0 { // NB: no actual allocation takes place when boxing zero-sized types. return Ok(Box::new(MaybeUninit::uninit())); } // Safety: layout size is non-zero. let ptr = unsafe { try_alloc(layout)? }; let ptr = ptr.cast::>(); // Safety: The pointer's memory block was allocated by the global allocator. Ok(unsafe { Box::from_raw(ptr.as_ptr()) }) }