xref: /wasmtime-44.0.1/crates/core/src/error/ptr.rs (revision 5afb6030)
1 //! Newtype wrappers over raw pointers that document ownership. We use these in
2 //! various places instead of safe references because our type-punning would
3 //! trigger UB otherwise.
4 
5 use core::{marker::PhantomData, ptr::NonNull};
6 use std_alloc::boxed::Box;
7 
8 /// A raw, owned pointer.
9 ///
10 /// You are required to call `T`'s `Drop` and deallocate the pointer, this won't
11 /// automatically do it for you like `Box`.
12 #[repr(transparent)]
13 pub(crate) struct OwnedPtr<T>
14 where
15     T: ?Sized,
16 {
17     ptr: NonNull<T>,
18 }
19 
20 impl<T> OwnedPtr<T> {
new(ptr: NonNull<T>) -> Self21     pub(crate) fn new(ptr: NonNull<T>) -> Self {
22         OwnedPtr { ptr }
23     }
24 
cast<U>(self) -> OwnedPtr<U>25     pub(crate) fn cast<U>(self) -> OwnedPtr<U> {
26         OwnedPtr::new(self.ptr.cast())
27     }
28 
29     /// Make a raw copy of this pointer.
raw_copy(&self) -> Self30     pub(crate) fn raw_copy(&self) -> Self {
31         Self::new(self.ptr)
32     }
33 
into_non_null(self) -> NonNull<T>34     pub(crate) fn into_non_null(self) -> NonNull<T> {
35         self.ptr
36     }
37 
38     /// # Safety
39     ///
40     /// It must be valid to call `NonNull::<T>::as_ref` on our underlying pointer.
as_ref(&self) -> &T41     pub(crate) unsafe fn as_ref(&self) -> &T {
42         unsafe { self.ptr.as_ref() }
43     }
44 
45     /// # Safety
46     ///
47     /// It must be valid to call `Box::<T>::from_raw` on our underlying pointer.
into_box(self) -> Box<T>48     pub(crate) unsafe fn into_box(self) -> Box<T> {
49         // Safety: same as our safety contract.
50         unsafe { Box::from_raw(self.ptr.as_ptr()) }
51     }
52 }
53 
54 /// A raw pointer that is semantically a shared borrow.
55 #[repr(transparent)]
56 pub(crate) struct SharedPtr<'a, T>
57 where
58     T: ?Sized,
59 {
60     ptr: NonNull<T>,
61     _lifetime: PhantomData<&'a T>,
62 }
63 
64 impl<'a, T> core::fmt::Debug for SharedPtr<'a, T>
65 where
66     T: ?Sized,
67 {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result68     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
69         f.debug_struct("SharedPtr").field("ptr", &self.ptr).finish()
70     }
71 }
72 
73 impl<T> Clone for SharedPtr<'_, T>
74 where
75     T: ?Sized,
76 {
clone(&self) -> Self77     fn clone(&self) -> Self {
78         *self
79     }
80 }
81 
82 impl<'a, T> SharedPtr<'a, T>
83 where
84     T: ?Sized,
85 {
new(ptr: NonNull<T>) -> Self86     pub(crate) fn new(ptr: NonNull<T>) -> Self {
87         SharedPtr {
88             ptr,
89             _lifetime: PhantomData,
90         }
91     }
92 
cast<U>(self) -> SharedPtr<'a, U>93     pub(crate) fn cast<U>(self) -> SharedPtr<'a, U> {
94         SharedPtr::new(self.ptr.cast())
95     }
96 
97     /// # Safety
98     ///
99     /// It must be valid to call `NonNull::<T>::as_ref` on the underlying
100     /// pointer.
as_ref(self) -> &'a T101     pub(crate) unsafe fn as_ref(self) -> &'a T {
102         unsafe { self.ptr.as_ref() }
103     }
104 }
105 
106 impl<T> Copy for SharedPtr<'_, T> where T: ?Sized {}
107 
108 /// A raw pointer that is semantically an exclusive borrow.
109 #[repr(transparent)]
110 pub(crate) struct MutPtr<'a, T>
111 where
112     T: ?Sized,
113 {
114     ptr: NonNull<T>,
115     _lifetime: PhantomData<&'a mut T>,
116 }
117 
118 impl<'a, T> MutPtr<'a, T>
119 where
120     T: ?Sized,
121 {
new(ptr: NonNull<T>) -> Self122     pub(crate) fn new(ptr: NonNull<T>) -> Self {
123         MutPtr {
124             ptr,
125             _lifetime: PhantomData,
126         }
127     }
128 
129     /// Make a raw copy of this pointer.
raw_copy(&self) -> Self130     pub(crate) fn raw_copy(&self) -> Self {
131         Self::new(self.ptr)
132     }
133 
cast<U>(self) -> MutPtr<'a, U>134     pub(crate) fn cast<U>(self) -> MutPtr<'a, U> {
135         MutPtr::new(self.ptr.cast())
136     }
137 
138     /// # Safety
139     ///
140     /// It must be valid to call `NonNull::<T>::as_ref` on the underlying pointer.
as_ref(&self) -> &'a T141     pub(crate) unsafe fn as_ref(&self) -> &'a T {
142         unsafe { self.ptr.as_ref() }
143     }
144 
145     /// # Safety
146     ///
147     /// It must be valid to call `NonNull::<T>::as_mut` on the underlying pointer.
as_mut(&mut self) -> &'a mut T148     pub(crate) unsafe fn as_mut(&mut self) -> &'a mut T {
149         unsafe { self.ptr.as_mut() }
150     }
151 }
152