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}