konst/ptr.rs
1//! Const equivalents of raw pointer and [`NonNull`](core::ptr::NonNull) methods.
2
3use core::ptr::NonNull;
4
5/// Const equivalent of `&*raw_pointer`.
6///
7///
8/// # Safety
9///
10/// This function has the safety requirements of
11/// [`<*const>::as_ref`](https://doc.rust-lang.org/1.55.0/std/primitive.pointer.html#safety),
12/// in addition to requiring that `ptr` is not null.
13///
14/// # Example
15///
16/// ```rust
17/// use konst::ptr;
18///
19/// const F: &u8 = unsafe{ ptr::deref("foo".as_ptr()) };
20/// assert_eq!(F, &b'f');
21///
22/// const BAR: &[u8; 3] = unsafe{ ptr::deref("bar".as_ptr().cast::<[u8; 3]>()) };
23/// assert_eq!(BAR, b"bar");
24///
25///
26/// ```
27#[cfg(feature = "rust_1_56")]
28#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
29pub const unsafe fn deref<'a, T: ?Sized>(ptr: *const T) -> &'a T {
30 core::mem::transmute(ptr)
31}
32
33/// Const equivalent of `&mut *raw_pointer`.
34///
35///
36/// # Safety
37///
38/// This function has the safety requirements of
39/// [`<*const>::as_mut`](https://doc.rust-lang.org/1.55.0/std/primitive.pointer.html#safety-13),
40/// in addition to requiring that `ptr` is not null.
41///
42/// # Example
43///
44/// ```rust
45/// # #![feature(const_mut_refs)]
46/// use konst::ptr;
47///
48/// assert_eq!(ARR, [33, 35, 38]);
49///
50/// const ARR: [u8; 3] = unsafe {
51/// let mut arr = [3, 5, 8];
52/// mutate(&mut arr[0]);
53/// mutate(&mut arr[1]);
54/// mutate(&mut arr[2]);
55/// arr
56/// };
57///
58/// const unsafe fn mutate(x: *mut u8) {
59/// let mutt = ptr::deref_mut(x);
60/// *mutt += 30;
61/// }
62///
63/// ```
64#[cfg(feature = "mut_refs")]
65#[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
66pub const unsafe fn deref_mut<'a, T: ?Sized>(ptr: *mut T) -> &'a mut T {
67 core::mem::transmute(ptr)
68}
69
70/// Const equivalent of
71/// [`<*const>::as_ref`](https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref)
72///
73/// # Safety
74///
75/// This function has the same safety requirements as
76/// [`<*const>::as_ref`](https://doc.rust-lang.org/1.55.0/std/primitive.pointer.html#safety)
77///
78/// # Example
79///
80/// ```rust
81/// use konst::ptr;
82///
83/// use core::ptr::null;
84///
85/// const NONE: Option<&u8> = unsafe{ ptr::as_ref(null()) };
86/// const SOME: Option<&u8> = unsafe{ ptr::as_ref(&100) };
87///
88/// assert_eq!(NONE, None);
89/// assert_eq!(SOME, Some(&100));
90///
91///
92/// ```
93#[cfg(feature = "rust_1_56")]
94#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
95pub const unsafe fn as_ref<'a, T: ?Sized>(ptr: *const T) -> Option<&'a T> {
96 core::mem::transmute(ptr)
97}
98
99/// Const equivalent of
100/// [`<*const>::as_mut`](https://doc.rust-lang.org/std/primitive.pointer.html#method.as_mut)
101///
102/// # Safety
103///
104/// This function has the same safety requirements as
105/// [`<*const>::as_mut`](https://doc.rust-lang.org/1.55.0/std/primitive.pointer.html#safety-13).
106///
107/// # Example
108///
109/// ```rust
110/// # #![feature(const_mut_refs)]
111/// use konst::ptr;
112///
113/// assert_eq!(ARR, [83, 91, 104]);
114///
115/// const ARR: [u8; 3] = unsafe {
116/// let mut arr = [13, 21, 34];
117/// mutate(&mut arr[0]);
118/// mutate(&mut arr[1]);
119/// mutate(&mut arr[2]);
120/// mutate(std::ptr::null_mut()); // no-op
121/// arr
122/// };
123///
124/// const unsafe fn mutate(x: *mut u8) {
125/// if let Some(mutt) = ptr::as_mut(x) {
126/// *mutt += 70;
127/// }
128/// }
129/// ```
130#[cfg(feature = "mut_refs")]
131#[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
132pub const unsafe fn as_mut<'a, T: ?Sized>(ptr: *mut T) -> Option<&'a mut T> {
133 core::mem::transmute(ptr)
134}
135
136/// Const equivalent of
137/// [`<*const>::is_null`](https://doc.rust-lang.org/std/primitive.pointer.html#method.is_null)
138///
139/// # Example
140///
141/// ```rust
142/// use konst::ptr;
143///
144/// use core::ptr::null;
145///
146/// const NULL_IS_NULL: bool = unsafe{ ptr::is_null(null::<u8>()) };
147/// const REFF_IS_NULL: bool = unsafe{ ptr::is_null(&100) };
148///
149/// assert_eq!(NULL_IS_NULL, true);
150/// assert_eq!(REFF_IS_NULL, false);
151///
152///
153/// ```
154#[cfg(feature = "rust_1_56")]
155#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
156pub const fn is_null<'a, T: ?Sized>(ptr: *const T) -> bool {
157 unsafe {
158 matches!(
159 core::mem::transmute::<*const T, Option<NonNull<T>>>(ptr),
160 None
161 )
162 }
163}
164
165/// Const equivalents of [`NonNull`](core::ptr::NonNull) methods.
166pub mod nonnull {
167 use core::ptr::NonNull;
168
169 /// Const equivalent of [`NonNull::new`](core::ptr::NonNull::new).
170 ///
171 /// # Example
172 ///
173 /// ```rust
174 /// use konst::ptr::nonnull;
175 ///
176 /// use core::ptr::{NonNull, null_mut};
177 ///
178 /// const NONE: Option<NonNull<u8>> = unsafe{ nonnull::new(null_mut()) };
179 /// const SOME: Option<NonNull<u8>> = unsafe{ nonnull::new(&100 as *const _ as *mut _) };
180 ///
181 /// assert!(NONE.is_none());
182 /// assert_eq!(SOME.map(|x|unsafe{*x.as_ptr()}), Some(100));
183 ///
184 ///
185 /// ```
186 #[cfg(feature = "rust_1_56")]
187 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
188 pub const fn new<T: ?Sized>(ptr: *mut T) -> Option<NonNull<T>> {
189 unsafe { core::mem::transmute(ptr) }
190 }
191
192 /// Const equivalent of [`NonNull::as_ref`](core::ptr::NonNull::as_ref).
193 ///
194 /// # Safety
195 ///
196 /// This has [the same safety requirements as `NonNull::as_ref`
197 /// ](https://doc.rust-lang.org/1.55.0/core/ptr/struct.NonNull.html#safety-3)
198 ///
199 /// # Example
200 ///
201 /// ```rust
202 /// use konst::ptr::nonnull;
203 ///
204 /// use core::{
205 /// ptr::NonNull,
206 /// marker::PhantomData,
207 /// };
208 ///
209 /// const A: NonNull<u8> = nonnull::from_ref(&3);
210 /// const A_REF: &u8 = unsafe{ nonnull::as_ref(A) };
211 /// assert_eq!(A_REF, &3);
212 ///
213 /// const B: NonNull<str> = nonnull::from_ref("hello");
214 /// const B_REF: &str = unsafe{ nonnull::as_ref(B) };
215 /// assert_eq!(B_REF, "hello");
216 ///
217 /// ```
218 ///
219 #[cfg(feature = "rust_1_56")]
220 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_56")))]
221 pub const unsafe fn as_ref<'a, T: ?Sized>(ptr: NonNull<T>) -> &'a T {
222 core::mem::transmute(ptr)
223 }
224
225 /// Const equivalent of [`NonNull::as_mut`](core::ptr::NonNull::as_mut).
226 ///
227 /// # Safety
228 ///
229 /// This has [the same safety requirements as `NonNull::as_mut`
230 /// ](https://doc.rust-lang.org/1.55.0/std/ptr/struct.NonNull.html#safety-4)
231 ///
232 /// # Example
233 ///
234 /// ```rust
235 /// # #![feature(const_mut_refs)]
236 /// use konst::ptr::nonnull;
237 ///
238 /// use core::ptr::NonNull;
239 ///
240 /// assert_eq!(TUP, (13, 15, 18));
241 ///
242 /// const TUP: (u8, u8, u8) = unsafe {
243 /// let mut tuple = (3, 5, 8);
244 /// mutate(nonnull::from_mut(&mut tuple.0));
245 /// mutate(nonnull::from_mut(&mut tuple.1));
246 /// mutate(nonnull::from_mut(&mut tuple.2));
247 /// tuple
248 /// };
249 ///
250 /// const unsafe fn mutate(x: NonNull<u8>) {
251 /// *nonnull::as_mut(x) += 10;
252 /// }
253 ///
254 /// ```
255 ///
256 #[cfg(feature = "mut_refs")]
257 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
258 pub const unsafe fn as_mut<'a, T: ?Sized>(ptr: NonNull<T>) -> &'a mut T {
259 core::mem::transmute(ptr)
260 }
261
262 /// Const equivalent of
263 /// [`<NonNull<T> as From<&T>>::from`
264 /// ](https://doc.rust-lang.org/1.55.0/std/ptr/struct.NonNull.html#impl-From%3C%26%27_%20T%3E)
265 ///
266 /// # Example
267 ///
268 /// ```rust
269 /// use konst::ptr::nonnull;
270 ///
271 /// use core::ptr::NonNull;
272 ///
273 /// const H: NonNull<str> = unsafe{ nonnull::from_ref("hello") };
274 /// const W: NonNull<str> = unsafe{ nonnull::from_ref("world") };
275 ///
276 /// unsafe{
277 /// assert_eq!(H.as_ref(), "hello");
278 /// assert_eq!(W.as_ref(), "world");
279 /// }
280 /// ```
281 pub const fn from_ref<T: ?Sized>(reff: &T) -> NonNull<T> {
282 unsafe { NonNull::new_unchecked(reff as *const _ as *mut _) }
283 }
284
285 /// Const equivalent of
286 /// [`<NonNull<T> as From<&mut T>>::from`
287 /// ](https://doc.rust-lang.org/1.55.0/std/ptr/struct.NonNull.html#impl-From%3C%26%27_%20mut%20T%3E)
288 ///
289 /// # Example
290 ///
291 /// ```rust
292 /// # #![feature(const_mut_refs)]
293 /// use konst::ptr::nonnull as nn;
294 ///
295 /// use core::ptr::NonNull;
296 ///
297 /// assert_eq!(ARR, (5, 8, 3));
298 ///
299 /// const ARR: (u8, u8, u8) = unsafe {
300 /// let mut tup = (3, 5, 8);
301 /// swap(nn::from_mut(&mut tup.0), nn::from_mut(&mut tup.1));
302 /// swap(nn::from_mut(&mut tup.1), nn::from_mut(&mut tup.2));
303 /// tup
304 /// };
305 ///
306 /// const unsafe fn swap(x: NonNull<u8>, y: NonNull<u8>) {
307 /// let xm = nn::as_mut(x);
308 /// let ym = nn::as_mut(y);
309 /// let tmp = *xm;
310 /// *xm = *ym;
311 /// *ym = tmp;
312 /// }
313 ///
314 /// ```
315 ///
316 #[cfg(feature = "mut_refs")]
317 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
318 pub const fn from_mut<T: ?Sized>(mutt: &mut T) -> NonNull<T> {
319 unsafe { NonNull::new_unchecked(mutt) }
320 }
321}