1use alloc::boxed::Box;
2use core::{
3 ffi::c_void,
4 marker::PhantomData,
5 mem::{self, ManuallyDrop},
6 ops::Deref,
7 ptr,
8};
9
10#[derive(Clone, Copy)]
11pub struct PtrMetadata<'a, T> {
13 pub ptr_value: usize,
14 _container: PhantomData<&'a T>,
15}
16
17impl<'a, R: CPtr<'a, Type = T>, T> PtrMetadata<'a, R> {
18 pub unsafe fn into_original_ptr(self) -> R {
19 mem::transmute_copy(&self.ptr_value)
20 }
21}
22
23pub unsafe trait CPtr<'a>: Sized {
25 type Type: Sized;
26
27 fn as_ptr(&self) -> *const Self::Type;
28
29 fn into_ptr(self) -> *const Self::Type {
30 let this = ManuallyDrop::new(self);
31 this.as_ptr()
32 }
33
34 fn metadata(&self) -> PtrMetadata<'a, Self> {
35 PtrMetadata { ptr_value: self.as_ptr() as usize, _container: PhantomData }
36 }
37}
38
39pub unsafe trait CMutPtr<'a>: CPtr<'a> {
41 fn as_mut_ptr(&mut self) -> *mut Self::Type {
42 <Self as CPtr>::as_ptr(self) as *mut _
43 }
44
45 fn into_mut_ptr(self) -> *mut Self::Type {
46 let mut this = ManuallyDrop::new(self);
47 this.as_mut_ptr()
48 }
49}
50
51pub unsafe trait CRef<'a>: CPtr<'a> {
53 fn as_ref(&self) -> &Self::Type {
54 unsafe { self.as_ptr().as_ref().unwrap() }
55 }
56}
57
58pub unsafe trait CMutRef<'a>: CRef<'a> + CMutPtr<'a> {
60 fn as_mut(&mut self) -> &mut Self::Type {
61 unsafe { self.as_mut_ptr().as_mut().unwrap() }
62 }
63}
64
65unsafe impl<'a, T> CPtr<'a> for &'a T {
67 type Type = T;
68
69 fn as_ptr(&self) -> *const Self::Type {
70 *self as *const _
71 }
72}
73unsafe impl<'a, T> CRef<'a> for &'a T {}
74
75unsafe impl<'a, T> CPtr<'a> for &'a mut T {
77 type Type = T;
78
79 fn as_ptr(&self) -> *const Self::Type {
80 *self as *const _
81 }
82}
83unsafe impl<'a, T> CRef<'a> for &'a mut T {}
84unsafe impl<'a, T> CMutPtr<'a> for &'a mut T {}
85unsafe impl<'a, T> CMutRef<'a> for &'a mut T {}
86
87unsafe impl<'a, T> CPtr<'a> for Box<T> {
89 type Type = T;
90
91 fn as_ptr(&self) -> *const Self::Type {
92 AsRef::as_ref(self) as *const _
93 }
94}
95unsafe impl<'a, T> CRef<'a> for Box<T> {}
96unsafe impl<'a, T> CMutPtr<'a> for Box<T> {}
97unsafe impl<'a, T> CMutRef<'a> for Box<T> {}
98
99unsafe impl CPtr<'static> for () {
101 type Type = c_void;
102
103 fn as_ptr(&self) -> *const Self::Type {
104 ptr::null()
105 }
106}
107
108unsafe impl CMutPtr<'static> for () {
109 fn as_mut_ptr(&mut self) -> *mut Self::Type {
110 ptr::null_mut()
111 }
112}
113
114unsafe impl<'a, R: CPtr<'a, Type = T>, T> CPtr<'a> for Option<R> {
116 type Type = T;
117
118 fn as_ptr(&self) -> *const Self::Type {
119 self.as_ref().map_or(ptr::null(), |p| p.as_ptr())
120 }
121}
122unsafe impl<'a, R: CMutPtr<'a, Type = T>, T> CMutPtr<'a> for Option<R> {}
123
124unsafe impl<'a, R: CPtr<'a, Type = T>, T> CPtr<'a> for ManuallyDrop<R> {
126 type Type = T;
127
128 fn as_ptr(&self) -> *const Self::Type {
129 <R as CPtr>::as_ptr(self.deref())
130 }
131}
132unsafe impl<'a, R: CMutPtr<'a, Type = T>, T> CMutPtr<'a> for ManuallyDrop<R> {}
133unsafe impl<'a, R: CRef<'a, Type = T>, T> CRef<'a> for ManuallyDrop<R> {}
134unsafe impl<'a, R: CMutRef<'a, Type = T>, T> CMutRef<'a> for ManuallyDrop<R> {}
135
136#[cfg(test)]
137mod test {
138 use core::ptr;
139
140 use super::*;
141
142 #[test]
143 fn test_ref() {
144 let mut foo = 10;
145 let ptr = ptr::addr_of!(foo);
146
147 assert_eq!(ptr, (&foo).as_ptr());
148 assert_eq!(ptr, (&mut foo).as_mut_ptr());
149
150 assert_eq!(ptr, (&foo).as_ref() as *const _);
151 assert_eq!(ptr, (&mut foo).as_mut() as *const _);
152
153 assert_eq!(ptr, (&mut foo).into_ptr());
154 let mut foo = 10;
155 let ptr = ptr::addr_of!(foo);
156 assert_eq!(ptr, (&mut foo).into_mut_ptr());
157 }
158
159 #[test]
160 fn test_box() {
161 let b = Box::new(10);
162 let b_ptr = ptr::from_ref(<Box<_> as AsRef<_>>::as_ref(&b));
163
164 assert_eq!(b_ptr, CPtr::as_ptr(&b));
165 assert_eq!(b_ptr, CPtr::into_ptr(b));
166
167 let mut b = unsafe { Box::from_raw(b_ptr as *mut i32) };
169 assert_eq!(&10, <Box<_> as AsRef<_>>::as_ref(&b));
170
171 assert_eq!(b_ptr, CMutPtr::as_mut_ptr(&mut b));
172 assert_eq!(b_ptr, CMutPtr::into_mut_ptr(b));
173 }
174
175 #[test]
176 fn test_unit_type() {
177 assert_eq!(ptr::null(), ().as_ptr());
178 assert_eq!(ptr::null_mut(), ().as_mut_ptr());
179 }
180
181 #[test]
182 fn test_option() {
183 assert_eq!(ptr::null(), (Option::<Box<i32>>::None).as_ptr());
184 assert_eq!(ptr::null_mut(), (Option::<Box<i32>>::None).as_mut_ptr());
185
186 let b = Box::new(10);
187 let ptr = b.as_ptr();
188 assert_eq!(ptr, Some(b).as_ptr());
189
190 let b = Box::new(10);
191 let ptr = b.as_ptr();
192 assert_eq!(ptr, Some(b).as_mut_ptr());
193
194 let b = Box::new(10);
195 let ptr = b.as_ptr();
196 assert_eq!(ptr, Some(b).into_ptr());
197
198 let b = Box::new(10);
199 let ptr = b.as_ptr();
200 assert_eq!(ptr, Some(b).into_mut_ptr());
201 }
202
203 #[test]
204 fn test_manually_drop() {
205 let b = Box::new(10);
206 let ptr = b.as_ptr();
207 let mut mdb = ManuallyDrop::new(b);
208 assert_eq!(ptr, mdb.as_ptr());
209 assert_eq!(ptr, mdb.as_mut_ptr());
210 assert_eq!(ptr, mdb.into_ptr());
211
212 let mdb = ManuallyDrop::new(unsafe { Box::from_raw(ptr as *mut i32) });
213 assert_eq!(ptr, mdb.into_mut_ptr());
214
215 assert_eq!(ptr::null(), ManuallyDrop::new(()).as_ptr());
216 assert_eq!(ptr::null_mut(), ManuallyDrop::new(()).as_mut_ptr());
217 }
218}