xref: /wasmtime-44.0.1/crates/core/src/alloc.rs (revision cbbe5551)
1 //! Low-level allocation and OOM-handling utilities.
2 
3 mod arc;
4 mod boxed;
5 mod try_clone;
6 mod try_collect;
7 mod try_new;
8 mod vec;
9 
10 pub 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 };
15 pub use try_clone::TryClone;
16 pub use try_collect::{TryCollect, TryExtend, TryFromIterator};
17 pub use try_new::{TryNew, try_new};
18 pub use vec::Vec;
19 
20 use crate::error::OutOfMemory;
21 use 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]
30 unsafe 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]
51 unsafe 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.
73 pub 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 
81 impl<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 }
92