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