xref: /wasmtime-44.0.1/crates/core/src/alloc.rs (revision 183891f0)
1 //! Low-level allocation and OOM-handling utilities.
2 
3 mod arc;
4 mod boxed;
5 mod string;
6 mod try_clone;
7 mod try_collect;
8 mod try_cow;
9 mod try_new;
10 mod vec;
11 
12 pub use boxed::{
13     BoxedSliceFromFallibleIterError, TooFewItemsOrOom, boxed_slice_write_iter,
14     new_boxed_slice_from_fallible_iter, new_boxed_slice_from_iter,
15     new_boxed_slice_from_iter_with_len, new_uninit_boxed_slice,
16 };
17 pub use string::TryString;
18 pub use try_clone::TryClone;
19 pub use try_collect::{TryCollect, TryExtend, TryFromIterator};
20 pub use try_cow::{TryCow, TryToOwned};
21 pub use try_new::{TryNew, try_new};
22 pub use vec::TryVec;
23 
24 use crate::error::OutOfMemory;
25 use core::{alloc::Layout, ptr::NonNull};
26 
27 /// Try to allocate a block of memory that fits the given layout, or return an
28 /// `OutOfMemory` error.
29 ///
30 /// # Safety
31 ///
32 /// Same as `alloc::alloc::alloc`: layout must have non-zero size.
33 #[inline]
try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory>34 unsafe fn try_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {
35     // Safety: same as our safety conditions.
36     debug_assert!(layout.size() > 0);
37     let ptr = unsafe { std_alloc::alloc::alloc(layout) };
38 
39     if let Some(ptr) = NonNull::new(ptr) {
40         Ok(ptr)
41     } else {
42         Err(OutOfMemory::new(layout.size()))
43     }
44 }
45 
46 /// Tries to reallocate a block of memory, returning `OutOfMemory` on failure.
47 ///
48 /// Analogue of [`alloc::alloc::realloc`].
49 ///
50 /// # Safety
51 ///
52 /// Same as `alloc::alloc::realloc`: `ptr` must be allocated with `layout`,
53 /// `layout` must be nonzero in size, and `new_size` must be nonzero and valid.
54 #[inline]
try_realloc( ptr: *mut u8, layout: Layout, new_size: usize, ) -> Result<NonNull<u8>, OutOfMemory>55 unsafe fn try_realloc(
56     ptr: *mut u8,
57     layout: Layout,
58     new_size: usize,
59 ) -> Result<NonNull<u8>, OutOfMemory> {
60     // Safety: same as our safety conditions.
61     debug_assert!(layout.size() > 0);
62     debug_assert!(new_size > 0);
63     let ptr = unsafe { std_alloc::alloc::realloc(ptr, layout, new_size) };
64 
65     if let Some(ptr) = NonNull::new(ptr) {
66         Ok(ptr)
67     } else {
68         Err(OutOfMemory::new(new_size))
69     }
70 }
71 
72 /// An extension trait for ignoring `OutOfMemory` errors.
73 ///
74 /// Use this to unwrap a `Result<T, OutOfMemory>` into its inner `T` or
75 /// otherwise panic, leveraging the type system to be sure that you aren't ever
76 /// accidentally unwrapping non-`OutOfMemory` errors.
77 pub trait PanicOnOom {
78     /// The non-`OutOfMemory` result of calling `panic_on_oom`.
79     type Result;
80 
81     /// Panic on `OutOfMemory` errors, returning the non-`OutOfMemory` result.
panic_on_oom(self) -> Self::Result82     fn panic_on_oom(self) -> Self::Result;
83 }
84 
85 impl<T> PanicOnOom for Result<T, OutOfMemory> {
86     type Result = T;
87 
88     #[track_caller]
panic_on_oom(self) -> Self::Result89     fn panic_on_oom(self) -> Self::Result {
90         match self {
91             Ok(x) => x,
92             Err(oom) => panic!("unhandled out-of-memory error: {oom}"),
93         }
94     }
95 }
96 
97 /// Create a `*mut str` from a pointer and length pair.
98 ///
99 /// NB: This function is safe, but dereferencing it or otherwise using the
100 /// resulting `str` pointer's contents is unsafe and requires that the pointer
101 /// be valid for accessing and points to a valid utf8 sequence of `len` bytes.
str_ptr_from_raw_parts(ptr: *mut u8, len: usize) -> *mut str102 fn str_ptr_from_raw_parts(ptr: *mut u8, len: usize) -> *mut str {
103     let ptr: *mut [u8] = core::ptr::slice_from_raw_parts_mut(ptr, len);
104     str_ptr_from_slice_ptr(ptr)
105 }
106 
107 /// Create a `*mut str` from a slice pointer.
108 ///
109 /// NB: This function is safe, but dereferencing it or otherwise using the
110 /// resulting `str` pointer's contents is unsafe and requires that the pointer
111 /// be valid for accessing and points to a valid utf8 sequence of `len` bytes.
str_ptr_from_slice_ptr(ptr: *mut [u8]) -> *mut str112 fn str_ptr_from_slice_ptr(ptr: *mut [u8]) -> *mut str {
113     // SAFETY: `str` is a newtype of `[u8]`.
114     let ptr: *mut str = unsafe { core::mem::transmute(ptr) };
115     ptr
116 }
117