gfxd_sys/
ptr.rs

1/* SPDX-FileCopyrightText: © 2025 Decompollaborate */
2/* SPDX-License-Identifier: MIT */
3
4//! Pointer utilities.
5
6use core::{cmp, fmt, hash, ptr::NonNull};
7
8use crate::ffi;
9
10#[repr(C)]
11pub(crate) struct Opaque {
12    // https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
13    _data: [u8; 0],
14    _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
15}
16
17/// A wrapper around [`NonNull`] that is explicitly a `const` pointer.
18#[repr(transparent)]
19pub struct NonNullConst<T>(NonNull<T>)
20where
21    T: ?Sized;
22
23/// A wrapper around [`NonNull`] that is explicitly a `mut` pointer.
24#[repr(transparent)]
25pub struct NonNullMut<T>(NonNull<T>)
26where
27    T: ?Sized;
28
29impl<T> NonNullConst<T>
30where
31    T: ?Sized,
32{
33    /// Convert into a plain [`NonNull`].
34    #[inline]
35    #[must_use]
36    pub const fn into_nonnull(self) -> NonNull<T> {
37        self.0
38    }
39    /// Take a reference to the internal [`NonNull`].
40    #[inline]
41    #[must_use]
42    pub const fn as_nonnull(&self) -> &NonNull<T> {
43        &self.0
44    }
45
46    /// Creates a new `NonNullConst`.
47    ///
48    /// # Safety
49    ///
50    /// `ptr` must be non-null.
51    #[inline]
52    #[must_use]
53    pub const unsafe fn new_unchecked(ptr: *const T) -> Self {
54        // NonNull wants a mut pointer for whatever reason.
55        let mut_ptr = cast_mut(ptr);
56
57        // SAFETY: the caller must guarantee that `ptr` is non-null.
58        let inner = unsafe { NonNull::new_unchecked(mut_ptr) };
59
60        Self(inner)
61    }
62
63    /// Creates a new `NonNullConst` if `ptr` is non-null.
64    #[inline]
65    #[must_use]
66    pub fn new(ptr: *const T) -> Option<Self> {
67        // NonNull wants a mut pointer for whatever reason.
68        let mut_ptr = cast_mut(ptr);
69
70        NonNull::new(mut_ptr).map(Self)
71    }
72
73    /// Converts a reference to a `NonNullConst` pointer.
74    #[inline]
75    #[must_use]
76    pub const fn from_ref(r: &T) -> Self {
77        // SAFETY: A reference cannot be null.
78        unsafe { Self::new_unchecked(r) }
79    }
80
81    /// Acquires the underlying `*const` pointer.
82    #[inline]
83    #[must_use]
84    pub const fn as_ptr(&self) -> *const T {
85        self.0.as_ptr()
86    }
87
88    /// Returns a shared reference to the value.
89    ///
90    /// # Safety
91    ///
92    /// When calling this method, you have to ensure that
93    /// the pointer is [convertible to a reference](core::ptr#pointer-to-reference-conversion).
94    #[inline]
95    #[must_use]
96    pub unsafe fn as_ref<'a>(&self) -> &'a T {
97        // SAFETY: the caller must guarantee that `self` meets all the
98        // requirements for a reference.
99        unsafe { &*self.as_ptr() }
100    }
101
102    /// Casts to a pointer of another type.
103    #[inline]
104    #[must_use]
105    pub const fn cast<U>(self) -> NonNullConst<U> {
106        let ptr = const_cast_to(self.0.as_ptr());
107
108        // SAFETY: `self` is known to be a non-null pointer
109        unsafe { NonNullConst::new_unchecked(ptr) }
110    }
111}
112
113impl NonNullConst<ffi::c_void> {
114    /// Creates a new `NonNullConst`, casting the passsed pointer to void
115    /// pointer.
116    ///
117    /// # Safety
118    ///
119    /// `ptr` must be non-null.
120    #[inline]
121    #[must_use]
122    pub const unsafe fn new_void_unchecked<U>(ptr: *const U) -> Self
123    where
124        U: ?Sized,
125    {
126        // Cast to void pointer.
127        let void_ptr: *const ffi::c_void = const_cast_to(ptr);
128        // NonNull wants a mut pointer for whatever reason.
129        let mut_void_ptr = cast_mut(void_ptr);
130
131        // SAFETY: the caller must guarantee that `ptr` is non-null.
132        let inner = unsafe { NonNull::new_unchecked(mut_void_ptr) };
133
134        Self(inner)
135    }
136
137    /// Creates a new `NonNullConst` if `ptr` is non-null, casting the pointer
138    /// to a void pointer.
139    #[inline]
140    #[must_use]
141    pub fn new_void<U>(ptr: *const U) -> Option<Self>
142    where
143        U: ?Sized,
144    {
145        // Cast to void pointer.
146        let void_ptr: *const ffi::c_void = const_cast_to(ptr);
147        // NonNull wants a mut pointer for whatever reason.
148        let mut_void_ptr = cast_mut(void_ptr);
149
150        NonNull::new(mut_void_ptr).map(Self)
151    }
152}
153
154#[cfg(feature = "std")]
155impl NonNullConst<ffi::c_char> {
156    /// # Safety
157    ///
158    /// The pointer pointed to be `self` must be a valid C string.
159    ///
160    /// Refer to [`CStr::from_ptr`] for details.
161    ///
162    /// [`CStr::from_ptr`]: std::ffi::CStr::from_ptr
163    #[inline]
164    #[must_use]
165    pub unsafe fn as_c_str(&self) -> &std::ffi::CStr {
166        unsafe { std::ffi::CStr::from_ptr(self.as_ptr()) }
167    }
168}
169
170impl<T> NonNullMut<T>
171where
172    T: ?Sized,
173{
174    /// Convert into a plain [`NonNull`].
175    #[inline]
176    #[must_use]
177    pub const fn into_nonnull(self) -> NonNull<T> {
178        self.0
179    }
180    /// Take a reference to the internal [`NonNull`].
181    #[inline]
182    #[must_use]
183    pub const fn as_nonnull(&self) -> &NonNull<T> {
184        &self.0
185    }
186
187    /// Creates a new `NonNullMut`.
188    ///
189    /// # Safety
190    ///
191    /// `ptr` must be non-null.
192    #[inline]
193    #[must_use]
194    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
195        // SAFETY: the caller must guarantee that `ptr` is non-null.
196        let inner = unsafe { NonNull::new_unchecked(ptr) };
197
198        Self(inner)
199    }
200
201    /// Creates a new `NonNullMut` if `ptr` is non-null.
202    #[inline]
203    #[must_use]
204    pub fn new(ptr: *mut T) -> Option<Self> {
205        NonNull::new(ptr).map(Self)
206    }
207
208    /// Converts a mutable reference to a `NonNullMut` pointer.
209    #[inline]
210    #[must_use]
211    pub fn from_mut(r: &mut T) -> Self {
212        // SAFETY: A mutable reference cannot be null.
213        unsafe { Self::new_unchecked(r) }
214    }
215
216    /// Acquires the underlying `*const` pointer.
217    #[inline]
218    #[must_use]
219    pub const fn as_ptr(&self) -> *mut T {
220        self.0.as_ptr()
221    }
222
223    /// Returns an unique reference to the value.
224    ///
225    /// # Safety
226    ///
227    /// When calling this method, you have to ensure that
228    /// the pointer is [convertible to a reference](core::ptr#pointer-to-reference-conversion).
229    #[inline]
230    #[must_use]
231    pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
232        unsafe { &mut *self.as_ptr() }
233    }
234
235    /// Casts to a pointer of another type.
236    #[inline]
237    #[must_use]
238    pub const fn cast<U>(self) -> NonNullMut<U> {
239        let ptr = mut_cast_to(self.0.as_ptr());
240
241        // SAFETY: `self` is known to be a non-null pointer
242        unsafe { NonNullMut::new_unchecked(ptr) }
243    }
244
245    /// Casts to a const pointer of the same type.
246    #[inline]
247    #[must_use]
248    pub const fn cast_const(self) -> NonNullConst<T> {
249        let ptr = cast_const(self.0.as_ptr());
250
251        // SAFETY: `self` is known to be a non-null pointer
252        unsafe { NonNullConst::new_unchecked(ptr) }
253    }
254}
255
256impl NonNullMut<ffi::c_void> {
257    /// Creates a new `NonNullMut`, casting the passsed pointer to void
258    /// pointer.
259    ///
260    /// # Safety
261    ///
262    /// `ptr` must be non-null.
263    #[inline]
264    #[must_use]
265    pub const unsafe fn new_void_unchecked<U>(ptr: *mut U) -> Self
266    where
267        U: ?Sized,
268    {
269        // Cast to void pointer.
270        let void_ptr: *mut ffi::c_void = mut_cast_to(ptr);
271
272        // SAFETY: the caller must guarantee that `ptr` is non-null.
273        let inner = unsafe { NonNull::new_unchecked(void_ptr) };
274
275        Self(inner)
276    }
277
278    /// Creates a new `NonNullMut` if `ptr` is non-null, casting the pointer to
279    /// a void pointer.
280    #[inline]
281    #[must_use]
282    pub fn new_void<U>(ptr: *mut U) -> Option<Self>
283    where
284        U: ?Sized,
285    {
286        // Cast to void pointer.
287        let void_ptr: *mut ffi::c_void = mut_cast_to(ptr);
288
289        NonNull::new(void_ptr).map(Self)
290    }
291}
292
293impl<T> fmt::Debug for NonNullConst<T>
294where
295    T: ?Sized,
296{
297    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298        // Use inner's impl
299        fmt::Debug::fmt(&self.0, f)
300    }
301}
302impl<T> fmt::Pointer for NonNullConst<T>
303where
304    T: ?Sized,
305{
306    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307        // Use inner's impl
308        fmt::Pointer::fmt(&self.0, f)
309    }
310}
311
312impl<T> Clone for NonNullConst<T>
313where
314    T: ?Sized,
315{
316    #[inline(always)]
317    fn clone(&self) -> Self {
318        *self
319    }
320}
321impl<T> Copy for NonNullConst<T> where T: ?Sized {}
322
323impl<T> PartialEq for NonNullConst<T>
324where
325    T: ?Sized,
326{
327    #[inline]
328    fn eq(&self, other: &Self) -> bool {
329        // Use inner's impl
330        #[allow(ambiguous_wide_pointer_comparisons)]
331        self.0.eq(&other.0)
332    }
333}
334impl<T> Eq for NonNullConst<T> where T: ?Sized {}
335
336impl<T> PartialOrd for NonNullConst<T>
337where
338    T: ?Sized,
339{
340    #[inline]
341    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
342        Some(self.cmp(other))
343    }
344}
345impl<T> Ord for NonNullConst<T>
346where
347    T: ?Sized,
348{
349    #[inline]
350    fn cmp(&self, other: &Self) -> cmp::Ordering {
351        // Use inner's impl
352        #[allow(ambiguous_wide_pointer_comparisons)]
353        self.0.cmp(&other.0)
354    }
355}
356
357impl<T> hash::Hash for NonNullConst<T>
358where
359    T: ?Sized,
360{
361    #[inline]
362    fn hash<H: hash::Hasher>(&self, state: &mut H) {
363        // Use inner's impl
364        self.0.hash(state)
365    }
366}
367
368impl<T> From<&T> for NonNullConst<T>
369where
370    T: ?Sized,
371{
372    /// Converts a `&T` to a `NonNullConst<T>`.
373    ///
374    /// This conversion is safe and infallible since references cannot be null.
375    #[inline]
376    fn from(r: &T) -> Self {
377        Self::from_ref(r)
378    }
379}
380
381impl<T> fmt::Debug for NonNullMut<T>
382where
383    T: ?Sized,
384{
385    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386        // Use inner's impl
387        fmt::Debug::fmt(&self.0, f)
388    }
389}
390impl<T> fmt::Pointer for NonNullMut<T>
391where
392    T: ?Sized,
393{
394    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395        // Use inner's impl
396        fmt::Pointer::fmt(&self.0, f)
397    }
398}
399
400impl<T> Clone for NonNullMut<T>
401where
402    T: ?Sized,
403{
404    #[inline(always)]
405    fn clone(&self) -> Self {
406        *self
407    }
408}
409impl<T> Copy for NonNullMut<T> where T: ?Sized {}
410
411impl<T> PartialEq for NonNullMut<T>
412where
413    T: ?Sized,
414{
415    #[inline]
416    fn eq(&self, other: &Self) -> bool {
417        // Use inner's impl
418        #[allow(ambiguous_wide_pointer_comparisons)]
419        self.0.eq(&other.0)
420    }
421}
422impl<T> Eq for NonNullMut<T> where T: ?Sized {}
423
424impl<T> PartialOrd for NonNullMut<T>
425where
426    T: ?Sized,
427{
428    #[inline]
429    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
430        Some(self.cmp(other))
431    }
432}
433impl<T> Ord for NonNullMut<T>
434where
435    T: ?Sized,
436{
437    #[inline]
438    fn cmp(&self, other: &Self) -> cmp::Ordering {
439        // Use inner's impl
440        #[allow(ambiguous_wide_pointer_comparisons)]
441        self.0.cmp(&other.0)
442    }
443}
444
445impl<T> hash::Hash for NonNullMut<T>
446where
447    T: ?Sized,
448{
449    #[inline]
450    fn hash<H: hash::Hasher>(&self, state: &mut H) {
451        // Use inner's impl
452        self.0.hash(state)
453    }
454}
455
456impl<T> From<&mut T> for NonNullMut<T>
457where
458    T: ?Sized,
459{
460    /// Converts a `&mut T` to a `NonNullMut<T>`.
461    ///
462    /// This conversion is safe and infallible since references cannot be null.
463    #[inline]
464    fn from(r: &mut T) -> Self {
465        Self::from_mut(r)
466    }
467}
468
469const fn cast_mut<T>(p: *const T) -> *mut T
470where
471    T: ?Sized,
472{
473    p as _
474}
475
476const fn cast_const<T>(p: *mut T) -> *const T
477where
478    T: ?Sized,
479{
480    p as _
481}
482
483const fn const_cast_to<T, U>(p: *const T) -> *const U
484where
485    T: ?Sized,
486{
487    p as _
488}
489
490const fn mut_cast_to<T, U>(p: *mut T) -> *mut U
491where
492    T: ?Sized,
493{
494    p as _
495}