abi_stable/sabi_types/static_ref.rs
1use crate::pointer_trait::{AsPtr, CanTransmuteElement, GetPointerKind, PK_Reference};
2
3use std::{
4 fmt::{self, Display},
5 ops::Deref,
6 ptr::NonNull,
7};
8
9/// A wrapper type for vtable static references,
10/// and other constants that have `non-'static` generic parameters
11/// but are safe to reference for the lifetime of `T`.
12///
13/// # Purpose
14///
15/// This type is necessary because Rust doesn't understand that vtables live for `'static`,
16/// even though they have `non-'static` type parameters.
17///
18/// # Example
19///
20/// This defines a non-extensible vtable,using a StaticRef as the pointer to the vtable.
21///
22/// ```
23/// use abi_stable::{
24/// marker_type::ErasedObject,
25/// prefix_type::{PrefixTypeTrait, WithMetadata},
26/// sabi_extern_fn,
27/// sabi_types::StaticRef,
28/// staticref, StableAbi,
29/// };
30///
31/// use std::{marker::PhantomData, ops::Deref};
32///
33/// fn main() {
34/// let boxed = BoxLike::new("foo".to_string());
35/// assert_eq!(boxed.as_str(), "foo");
36/// }
37///
38/// /// An ffi-safe `Box<T>`
39/// #[repr(C)]
40/// #[derive(StableAbi)]
41/// pub struct BoxLike<T> {
42/// data: *mut T,
43///
44/// vtable: StaticRef<VTable<T>>,
45///
46/// _marker: PhantomData<T>,
47/// }
48///
49/// impl<T> BoxLike<T> {
50/// pub fn new(value: T) -> Self {
51/// Self {
52/// data: Box::into_raw(Box::new(value)),
53/// vtable: VTable::<T>::VTABLE,
54/// _marker: PhantomData,
55/// }
56/// }
57/// }
58///
59/// impl<T> Drop for BoxLike<T> {
60/// fn drop(&mut self) {
61/// unsafe {
62/// (self.vtable.drop_)(self.data);
63/// }
64/// }
65/// }
66///
67/// impl<T> Deref for BoxLike<T> {
68/// type Target = T;
69///
70/// fn deref(&self) -> &T {
71/// unsafe { &*self.data }
72/// }
73/// }
74///
75/// #[repr(C)]
76/// #[derive(StableAbi)]
77/// pub struct VTable<T> {
78/// drop_: unsafe extern "C" fn(*mut T),
79/// }
80///
81/// impl<T> VTable<T> {
82/// // The `staticref` macro declares a `StaticRef<VTable<T>>` constant.
83/// staticref!(const VTABLE: Self = Self{
84/// drop_: drop_box::<T>,
85/// });
86/// }
87///
88/// #[sabi_extern_fn]
89/// unsafe fn drop_box<T>(object: *mut T) {
90/// drop(Box::from_raw(object));
91/// }
92///
93/// ```
94#[repr(transparent)]
95#[derive(StableAbi)]
96pub struct StaticRef<T> {
97 ref_: NonNull<T>,
98}
99
100impl<T> Display for StaticRef<T>
101where
102 T: Display,
103{
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 Display::fmt(&**self, f)
106 }
107}
108
109impl<T> Clone for StaticRef<T> {
110 fn clone(&self) -> Self {
111 *self
112 }
113}
114
115impl<T> Copy for StaticRef<T> {}
116
117unsafe impl<'a, T: 'a> Sync for StaticRef<T> where &'a T: Sync {}
118
119unsafe impl<'a, T: 'a> Send for StaticRef<T> where &'a T: Send {}
120
121shared_impls! {
122 mod=static_ref_impls
123 new_type=StaticRef[][T],
124 original_type=AAAA,
125}
126
127impl<T> StaticRef<T> {
128 /// Constructs this StaticRef from a raw pointer.
129 ///
130 /// # Safety
131 ///
132 /// You must ensure that the raw pointer is valid for the entire program's lifetime.
133 ///
134 /// # Example
135 ///
136 /// ```
137 /// use abi_stable::sabi_types::StaticRef;
138 ///
139 /// struct GetPtr<T>(T);
140 ///
141 /// impl<T> GetPtr<T> {
142 /// const PTR: *const Option<T> = &None;
143 ///
144 /// const STATIC: StaticRef<Option<T>> = unsafe { StaticRef::from_raw(Self::PTR) };
145 /// }
146 /// {}
147 /// ```
148 pub const unsafe fn from_raw(ref_: *const T) -> Self {
149 Self {
150 ref_: unsafe { NonNull::new_unchecked(ref_ as *mut T) },
151 }
152 }
153
154 /// Constructs this StaticRef from a static reference
155 ///
156 /// This implicitly requires that `T:'static`.
157 ///
158 /// # Example
159 ///
160 /// ```
161 /// use abi_stable::sabi_types::StaticRef;
162 ///
163 /// struct GetPtr<T>(T);
164 ///
165 /// impl<T> GetPtr<T>
166 /// where
167 /// T: 'static,
168 /// {
169 /// const REF: &'static Option<T> = &None;
170 ///
171 /// const STATIC: StaticRef<Option<T>> = StaticRef::new(Self::REF);
172 /// }
173 ///
174 /// ```
175 pub const fn new(ref_: &'static T) -> Self {
176 Self {
177 ref_: unsafe { NonNull::new_unchecked(ref_ as *const T as *mut T) },
178 }
179 }
180
181 /// Creates a StaticRef by heap allocating and leaking `val`.
182 pub fn leak_value(val: T) -> Self {
183 // Safety: This is safe, because the value is a leaked heap allocation.
184 unsafe { Self::from_raw(crate::utils::leak_value(val)) }
185 }
186
187 /// Gets access to the reference.
188 ///
189 /// This returns `&'a T` instead of `&'static T` to support vtables of `non-'static` types.
190 ///
191 /// # Example
192 ///
193 /// ```
194 /// use abi_stable::sabi_types::StaticRef;
195 ///
196 /// struct GetPtr<T>(T);
197 ///
198 /// impl<T> GetPtr<T> {
199 /// const PTR: *const Option<T> = &None;
200 ///
201 /// const STATIC: StaticRef<Option<T>> = unsafe { StaticRef::from_raw(Self::PTR) };
202 /// }
203 ///
204 /// let reference: &'static Option<String> = GetPtr::<String>::STATIC.get();
205 ///
206 /// ```
207 pub const fn get<'a>(self) -> &'a T {
208 unsafe { crate::utils::deref!(self.ref_.as_ptr() as *const T) }
209 }
210
211 /// Gets access to the referenced value,as a raw pointer.
212 ///
213 /// # Example
214 ///
215 /// ```
216 /// use abi_stable::sabi_types::StaticRef;
217 /// use std::convert::Infallible;
218 ///
219 /// struct GetPtr<T>(T);
220 ///
221 /// impl<T> GetPtr<T> {
222 /// const PTR: *const Option<T> = &None;
223 ///
224 /// const STATIC: StaticRef<Option<T>> = unsafe { StaticRef::from_raw(Self::PTR) };
225 /// }
226 ///
227 /// let reference: *const Option<Infallible> = GetPtr::<Infallible>::STATIC.as_ptr();
228 ///
229 /// ```
230 pub const fn as_ptr(self) -> *const T {
231 self.ref_.as_ptr() as *const T
232 }
233
234 /// Transmutes this `StaticRef<T>` to a `StaticRef<U>`.
235 ///
236 /// # Safety
237 ///
238 /// StaticRef has the same rules that references have regarding
239 /// transmuting from one type to another:
240 ///
241 /// # Example
242 ///
243 /// ```
244 /// use abi_stable::sabi_types::StaticRef;
245 ///
246 /// struct GetPtr<T>(T);
247 ///
248 /// impl<T> GetPtr<T> {
249 /// const PTR: *const Option<T> = &None;
250 ///
251 /// const STATIC: StaticRef<Option<T>> = unsafe { StaticRef::from_raw(Self::PTR) };
252 /// }
253 ///
254 /// let reference: StaticRef<Option<[(); 0xFFF_FFFF]>> =
255 /// unsafe { GetPtr::<()>::STATIC.transmute::<Option<[(); 0xFFF_FFFF]>>() };
256 ///
257 /// ```
258 pub const unsafe fn transmute<U>(self) -> StaticRef<U> {
259 unsafe { StaticRef::from_raw(self.ref_.as_ptr() as *const T as *const U) }
260 }
261}
262
263impl<T> Deref for StaticRef<T> {
264 type Target = T;
265
266 fn deref(&self) -> &T {
267 self.get()
268 }
269}
270
271unsafe impl<T> AsPtr for StaticRef<T> {
272 fn as_ptr(&self) -> *const T {
273 self.ref_.as_ptr() as *const T
274 }
275}
276
277unsafe impl<T> GetPointerKind for StaticRef<T> {
278 type Kind = PK_Reference;
279
280 type PtrTarget = T;
281}
282
283unsafe impl<T, U> CanTransmuteElement<U> for StaticRef<T> {
284 type TransmutedPtr = StaticRef<U>;
285
286 #[inline(always)]
287 unsafe fn transmute_element_(self) -> StaticRef<U> {
288 unsafe { self.transmute() }
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use super::*;
295
296 #[test]
297 fn construction_test() {
298 unsafe {
299 let three: *const i32 = &3;
300 assert_eq!(*StaticRef::from_raw(three), 3);
301 }
302
303 assert_eq!(*StaticRef::new(&5), 5);
304
305 assert_eq!(*StaticRef::leak_value(8), 8);
306 }
307
308 #[test]
309 fn access() {
310 let reference = StaticRef::new(&8);
311 const SREF: StaticRef<u8> = StaticRef::new(&8);
312 const REF: &u8 = SREF.get();
313
314 assert_eq!(*reference.get(), 8);
315 assert_eq!(*REF, 8);
316 unsafe {
317 assert_eq!(*reference.as_ptr(), 8);
318 }
319 }
320
321 #[test]
322 fn transmutes() {
323 let reference = StaticRef::new(&(!0u32));
324
325 unsafe {
326 assert_eq!(*reference.transmute::<i32>(), -1);
327 }
328 }
329}