use crate::error::{Error, OomOrDynError};1use core::{fmt, mem, ptr::NonNull};23/// Out-of-memory error.4///5/// This error is the sentinel for allocation failure due to memory exhaustion.6///7/// Constructing an [`Error`] from an `OutOfMemory` does not8/// allocate.9///10/// Allocation failure inside any `Error` method that must allocate11/// (e.g. [`Error::context`]) will propagate an `OutOfMemory` error.12#[derive(Clone, Copy)]13// NB: `OutOfMemory`'s representation must be the same as `OomOrDynError`14// (and therefore also `Error`).15#[repr(transparent)]16pub struct OutOfMemory {17inner: NonNull<u8>,18}1920// Safety: The `inner` pointer is not a real pointer, it is just bitpacked size21// data.22unsafe impl Send for OutOfMemory {}2324// Safety: The `inner` pointer is not a real pointer, it is just bitpacked size25// data.26unsafe impl Sync for OutOfMemory {}2728impl fmt::Debug for OutOfMemory {29fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {30f.debug_struct("OutOfMemory")31.field(32"requested_allocation_size",33&self.requested_allocation_size(),34)35.finish()36}37}3839impl fmt::Display for OutOfMemory {40fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {41write!(42f,43"out of memory (failed to allocate {} bytes)",44self.requested_allocation_size()45)46}47}4849impl core::error::Error for OutOfMemory {50#[inline]51fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {52None53}54}5556impl OutOfMemory {57// NB: `OutOfMemory`'s representation must be the same as `OomOrDynError`58// (and therefore also `Error`).59const _SAME_SIZE_AS_OOM_OR_DYN_ERROR: () =60assert!(mem::size_of::<OutOfMemory>() == mem::size_of::<OomOrDynError>());61const _SAME_ALIGN_AS_OOM_OR_DYN_ERROR: () =62assert!(mem::align_of::<OutOfMemory>() == mem::align_of::<OomOrDynError>());63const _SAME_SIZE_AS_ERROR: () =64assert!(mem::size_of::<OutOfMemory>() == mem::size_of::<Error>());65const _SAME_ALIGN_AS_ERROR: () =66assert!(mem::align_of::<OutOfMemory>() == mem::align_of::<Error>());6768/// Construct a new `OutOfMemory` error.69///70/// The `requested_allocation_size` argument should be the size (in bytes)71/// of the associated allocation that was attempted and failed.72///73/// This operation does not allocate.74///75/// # Example76///77/// ```rust78/// # use wasmtime_internal_core::error::OutOfMemory;79/// # extern crate alloc;80/// use alloc::alloc::{Layout, alloc};81/// use core::ptr::NonNull;82///83/// /// Attempt to allocate a block of memory from the global allocator,84/// /// returning an `OutOfMemory` error on failure.85/// fn try_global_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {86/// if layout.size() == 0 {87/// return Ok(NonNull::dangling());88/// }89///90/// // Safety: the layout's size is non-zero.91/// let ptr = unsafe { alloc(layout) };92///93/// if let Some(ptr) = NonNull::new(ptr) {94/// Ok(ptr)95/// } else {96/// // The allocation failed, so return an `OutOfMemory` error,97/// // passing the attempted allocation's size into the `OutOfMemory`98/// // constructor.99/// Err(OutOfMemory::new(layout.size()))100/// }101/// }102/// ```103#[inline]104pub const fn new(requested_allocation_size: usize) -> Self {105Self {106inner: OomOrDynError::new_oom_ptr(requested_allocation_size),107}108}109110/// Get the size (in bytes) of the associated allocation that was attempted111/// and which failed.112///113/// Very large allocation sizes (near `isize::MAX` and larger) may be capped114/// to a maximum value.115///116/// # Example117///118/// ```rust119/// # use wasmtime_internal_core::error::OutOfMemory;120/// let oom = OutOfMemory::new(8192);121/// assert_eq!(oom.requested_allocation_size(), 8192);122/// ```123#[inline]124pub fn requested_allocation_size(&self) -> usize {125OomOrDynError::oom_size(self.inner)126}127}128129impl From<OutOfMemory> for OomOrDynError {130fn from(oom: OutOfMemory) -> Self {131OomOrDynError::new_oom(oom.inner)132}133}134135136