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