Skip to main content

wasmtime_internal_core/
alloc.rs

1//! Low-level allocation and OOM-handling utilities.
2
3mod arc;
4mod boxed;
5mod try_clone;
6mod try_collect;
7mod try_new;
8mod vec;
9
10pub use boxed::{
11    BoxedSliceFromFallibleIterError, TooFewItemsOrOom, boxed_slice_write_iter,
12    new_boxed_slice_from_fallible_iter, new_boxed_slice_from_iter,
13    new_boxed_slice_from_iter_with_len, new_uninit_boxed_slice,
14};
15pub use try_clone::TryClone;
16pub use try_collect::{TryCollect, TryExtend, TryFromIterator};
17pub use try_new::{TryNew, try_new};
18pub use vec::Vec;
19
20use crate::error::OutOfMemory;
21use core::{alloc::Layout, ptr::NonNull};
22
23/// Try to allocate a block of memory that fits the given layout, or return an
24/// `OutOfMemory` error.
25///
26/// # Safety
27///
28/// Same as `alloc::alloc::alloc`: layout must have non-zero size.
29#[inline]
30unsafe fn try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {
31    // Safety: same as our safety conditions.
32    debug_assert!(layout.size() > 0);
33    let ptr = unsafe { std_alloc::alloc::alloc(layout) };
34
35    if let Some(ptr) = NonNull::new(ptr) {
36        Ok(ptr)
37    } else {
38        Err(OutOfMemory::new(layout.size()))
39    }
40}
41
42/// Tries to reallocate a block of memory, returning `OutOfMemory` on failure.
43///
44/// Analogue of [`alloc::alloc::realloc`].
45///
46/// # Safety
47///
48/// Same as `alloc::alloc::realloc`: `ptr` must be allocated with `layout`,
49/// `layout` must be nonzero in size, and `new_size` must be nonzero and valid.
50#[inline]
51unsafe fn try_realloc(
52    ptr: *mut u8,
53    layout: Layout,
54    new_size: usize,
55) -> Result<NonNull<u8>, OutOfMemory> {
56    // Safety: same as our safety conditions.
57    debug_assert!(layout.size() > 0);
58    debug_assert!(new_size > 0);
59    let ptr = unsafe { std_alloc::alloc::realloc(ptr, layout, new_size) };
60
61    if let Some(ptr) = NonNull::new(ptr) {
62        Ok(ptr)
63    } else {
64        Err(OutOfMemory::new(new_size))
65    }
66}
67
68/// An extension trait for ignoring `OutOfMemory` errors.
69///
70/// Use this to unwrap a `Result<T, OutOfMemory>` into its inner `T` or
71/// otherwise panic, leveraging the type system to be sure that you aren't ever
72/// accidentally unwrapping non-`OutOfMemory` errors.
73pub trait PanicOnOom {
74    /// The non-`OutOfMemory` result of calling `panic_on_oom`.
75    type Result;
76
77    /// Panic on `OutOfMemory` errors, returning the non-`OutOfMemory` result.
78    fn panic_on_oom(self) -> Self::Result;
79}
80
81impl<T> PanicOnOom for Result<T, OutOfMemory> {
82    type Result = T;
83
84    #[track_caller]
85    fn panic_on_oom(self) -> Self::Result {
86        match self {
87            Ok(x) => x,
88            Err(oom) => panic!("unhandled out-of-memory error: {oom}"),
89        }
90    }
91}