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}