const_util/
mem.rs

1use core::{
2    mem::ManuallyDrop,
3    ptr::{self, NonNull},
4};
5
6/// Gets a reference to the contents of a `ManuallyDrop`.
7///
8/// This function is a const version of the `Deref` implementation of `ManuallyDrop`.
9///
10/// # Example
11/// ```
12/// use const_util::mem::man_drop_ref;
13/// use core::mem::ManuallyDrop;
14/// assert_eq!(man_drop_ref(&ManuallyDrop::new(1)), &1);
15/// ```
16pub const fn man_drop_ref<T>(man: &ManuallyDrop<T>) -> &T {
17    // SAFETY: repr(transparent)
18    unsafe { &*ptr::from_ref(man).cast() }
19}
20/// Gets a reference to the contents of a `ManuallyDrop`.
21///
22/// This function is a const version of the `DerefMut` implementation of `ManuallyDrop`.
23///
24/// # Example
25/// ```
26/// use const_util::mem::man_drop_mut;
27/// use core::mem::ManuallyDrop;
28/// assert_eq!(man_drop_mut(&mut ManuallyDrop::new(1)), &mut 1);
29/// ```
30pub const fn man_drop_mut<T>(man: &mut ManuallyDrop<T>) -> &mut T {
31    // SAFETY: repr(transparent)
32    unsafe { &mut *ptr::from_mut(man).cast() }
33}
34
35/// Converts `&T` or `&mut T` into `NonNull<T>`.
36///
37/// This function is a const version of the `From<&T>` and `From<&mut T>` implementations of
38/// `NonNull<T>`. The returned pointer will have the same mutability as the argument.
39///
40/// This function is useful to avoid accidentally converting a mutable reference to an immutable
41/// one when copying around code.
42///
43/// # Example
44/// ```
45/// use const_util::mem::nonnull_from;
46/// use core::ptr::NonNull;
47///
48/// let mut x = 1;
49/// assert_eq!(
50///     nonnull_from(&x),
51///     NonNull::from(&x),
52/// );
53/// assert_eq!(
54///     nonnull_from(&mut x),
55///     NonNull::from(&mut x),
56/// );
57/// unsafe { nonnull_from(&mut x).write(2) };
58/// assert_eq!(unsafe { nonnull_from(&x).read() }, 2);
59/// ```
60pub const fn nonnull_from<T: ?Sized>(src: impl hidden::Reference<Referee = T>) -> NonNull<T> {
61    const fn doit<T: ?Sized, R: hidden::Reference<Referee = T>>(src: R) -> NonNull<R::Referee> {
62        let ptr: *mut T = {
63            let src = ManuallyDrop::new(src);
64            if R::MUTABLE {
65                // SAFETY: &mut T to *mut T transmute
66                let ptr: *mut T = unsafe { core::mem::transmute_copy(&src) };
67                ptr
68            } else {
69                // SAFETY: &T to *const T transmute
70                let ptr: *const T = unsafe { core::mem::transmute_copy(&src) };
71                ptr.cast_mut()
72            }
73        };
74        // SAFETY: References are non-null
75        unsafe { NonNull::new_unchecked(ptr) }
76    }
77    doit(src)
78}
79mod hidden {
80    /// # Safety
81    /// `Self` must be `&Referee` and `MUTABLE = false` or `&mut Referee` and `MUTABLE = true`
82    pub unsafe trait Reference: Into<core::ptr::NonNull<Self::Referee>> {
83        type Referee: ?Sized;
84        const MUTABLE: bool;
85    }
86    unsafe impl<T: ?Sized> Reference for &T {
87        type Referee = T;
88        const MUTABLE: bool = false;
89    }
90    unsafe impl<T: ?Sized> Reference for &mut T {
91        type Referee = T;
92        const MUTABLE: bool = true;
93    }
94}