facet_core/impls/core/
pointer.rs1use core::cmp::Ordering;
4use core::hash::Hash;
5
6use crate::{
7 Def, Facet, HashProxy, OxPtrConst, OxPtrMut, PointerType, Shape, ShapeBuilder, Type,
8 TypeOpsIndirect, TypeParam, VTableIndirect, ValuePointerType, Variance,
9};
10
11unsafe fn const_ptr_debug<T: ?Sized>(
16 ox: OxPtrConst,
17 f: &mut core::fmt::Formatter<'_>,
18) -> Option<core::fmt::Result> {
19 let p = unsafe { ox.ptr().get::<*const T>() };
20 Some(core::fmt::Debug::fmt(&p, f))
21}
22
23unsafe fn const_ptr_hash<T: ?Sized>(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
25 let p = unsafe { ox.ptr().get::<*const T>() };
26 p.hash(hasher);
27 Some(())
28}
29
30#[allow(ambiguous_wide_pointer_comparisons)]
32unsafe fn const_ptr_partial_eq<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
33 let a_val = unsafe { a.ptr().get::<*const T>() };
34 let b_val = unsafe { b.ptr().get::<*const T>() };
35 Some(*a_val == *b_val)
36}
37
38#[allow(ambiguous_wide_pointer_comparisons)]
40unsafe fn const_ptr_partial_cmp<T: ?Sized>(
41 a: OxPtrConst,
42 b: OxPtrConst,
43) -> Option<Option<Ordering>> {
44 let a_val = unsafe { a.ptr().get::<*const T>() };
45 let b_val = unsafe { b.ptr().get::<*const T>() };
46 Some(a_val.partial_cmp(b_val))
47}
48
49#[allow(ambiguous_wide_pointer_comparisons)]
51unsafe fn const_ptr_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Ordering> {
52 let a_val = unsafe { a.ptr().get::<*const T>() };
53 let b_val = unsafe { b.ptr().get::<*const T>() };
54 Some(a_val.cmp(b_val))
55}
56
57unsafe fn const_ptr_drop<T: ?Sized>(_ptr: OxPtrMut) {
59 }
61
62unsafe fn const_ptr_clone<T: ?Sized>(src: OxPtrConst, dst: OxPtrMut) {
64 let src_val = unsafe { src.ptr().get::<*const T>() };
65 let dst_ptr = unsafe { dst.ptr().as_mut::<*const T>() };
66 *dst_ptr = *src_val;
67}
68
69unsafe fn mut_ptr_debug<T: ?Sized>(
71 ox: OxPtrConst,
72 f: &mut core::fmt::Formatter<'_>,
73) -> Option<core::fmt::Result> {
74 let p = unsafe { ox.ptr().get::<*mut T>() };
75 Some(core::fmt::Debug::fmt(&p, f))
76}
77
78unsafe fn mut_ptr_hash<T: ?Sized>(ox: OxPtrConst, hasher: &mut HashProxy<'_>) -> Option<()> {
80 let p = unsafe { ox.ptr().get::<*mut T>() };
81 p.hash(hasher);
82 Some(())
83}
84
85#[allow(ambiguous_wide_pointer_comparisons)]
87unsafe fn mut_ptr_partial_eq<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
88 let a_val = unsafe { a.ptr().get::<*mut T>() };
89 let b_val = unsafe { b.ptr().get::<*mut T>() };
90 Some(*a_val == *b_val)
91}
92
93#[allow(ambiguous_wide_pointer_comparisons)]
95unsafe fn mut_ptr_partial_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Option<Ordering>> {
96 let a_val = unsafe { a.ptr().get::<*mut T>() };
97 let b_val = unsafe { b.ptr().get::<*mut T>() };
98 Some(a_val.partial_cmp(b_val))
99}
100
101#[allow(ambiguous_wide_pointer_comparisons)]
103unsafe fn mut_ptr_cmp<T: ?Sized>(a: OxPtrConst, b: OxPtrConst) -> Option<Ordering> {
104 let a_val = unsafe { a.ptr().get::<*mut T>() };
105 let b_val = unsafe { b.ptr().get::<*mut T>() };
106 Some(a_val.cmp(b_val))
107}
108
109unsafe fn mut_ptr_drop<T: ?Sized>(_ptr: OxPtrMut) {
111 }
113
114unsafe fn mut_ptr_clone<T: ?Sized>(src: OxPtrConst, dst: OxPtrMut) {
116 let src_val = unsafe { src.ptr().get::<*mut T>() };
117 let dst_ptr = unsafe { dst.ptr().as_mut::<*mut T>() };
118 *dst_ptr = *src_val;
119}
120
121unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *const T {
123 const SHAPE: &'static Shape = &const {
124 const fn build_const_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
125 VTableIndirect {
126 display: None,
127 debug: Some(const_ptr_debug::<T>),
128 hash: Some(const_ptr_hash::<T>),
129 invariants: None,
130 parse: None,
131 try_from: None,
132 try_into_inner: None,
133 try_borrow_inner: None,
134 partial_eq: Some(const_ptr_partial_eq::<T>),
135 partial_cmp: Some(const_ptr_partial_cmp::<T>),
136 cmp: Some(const_ptr_cmp::<T>),
137 }
138 }
139
140 const fn build_const_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
141 TypeOpsIndirect {
142 drop_in_place: const_ptr_drop::<T>,
143 default_in_place: None,
144 clone_into: Some(const_ptr_clone::<T>),
145 is_truthy: None,
146 }
147 }
148
149 ShapeBuilder::for_sized::<*const T>("*const T")
150 .ty({
151 let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
152 let vpt = ValuePointerType {
153 mutable: false,
154 wide: is_wide,
155 target: T::SHAPE,
156 };
157 Type::Pointer(PointerType::Raw(vpt))
158 })
159 .def(Def::Scalar)
160 .type_params(&[TypeParam {
161 name: "T",
162 shape: T::SHAPE,
163 }])
164 .inner(T::SHAPE)
165 .vtable_indirect(&const { build_const_ptr_vtable::<T>() })
166 .type_ops_indirect(&const { build_const_ptr_type_ops::<T>() })
167 .eq()
168 .copy()
169 .build()
170 };
171}
172
173unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
175 const SHAPE: &'static Shape = &const {
176 const fn build_mut_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
177 VTableIndirect {
178 display: None,
179 debug: Some(mut_ptr_debug::<T>),
180 hash: Some(mut_ptr_hash::<T>),
181 invariants: None,
182 parse: None,
183 try_from: None,
184 try_into_inner: None,
185 try_borrow_inner: None,
186 partial_eq: Some(mut_ptr_partial_eq::<T>),
187 partial_cmp: Some(mut_ptr_partial_cmp::<T>),
188 cmp: Some(mut_ptr_cmp::<T>),
189 }
190 }
191
192 const fn build_mut_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
193 TypeOpsIndirect {
194 drop_in_place: mut_ptr_drop::<T>,
195 default_in_place: None,
196 clone_into: Some(mut_ptr_clone::<T>),
197 is_truthy: None,
198 }
199 }
200
201 ShapeBuilder::for_sized::<*mut T>("*mut T")
202 .ty({
203 let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
204 let vpt = ValuePointerType {
205 mutable: true,
206 wide: is_wide,
207 target: T::SHAPE,
208 };
209 Type::Pointer(PointerType::Raw(vpt))
210 })
211 .def(Def::Scalar)
212 .type_params(&[TypeParam {
213 name: "T",
214 shape: T::SHAPE,
215 }])
216 .inner(T::SHAPE)
217 .vtable_indirect(&const { build_mut_ptr_vtable::<T>() })
218 .type_ops_indirect(&const { build_mut_ptr_type_ops::<T>() })
219 .variance(Variance::INVARIANT)
221 .eq()
222 .copy()
223 .build()
224 };
225}
226
227#[cfg(test)]
228mod test {
229 use core::panic::{RefUnwindSafe, UnwindSafe};
230
231 #[cfg(feature = "auto-traits")]
232 use impls::impls;
233
234 #[allow(unused)]
235 const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
236 #[allow(unused)]
237 const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
238
239 #[allow(unused)]
240 const fn ref_unwind_safe<T: RefUnwindSafe>() {
241 assert_impls_unwind_safe::<&T>();
242 assert_impls_ref_unwind_safe::<&T>();
243
244 assert_impls_ref_unwind_safe::<&mut T>();
245
246 assert_impls_unwind_safe::<*const T>();
247 assert_impls_ref_unwind_safe::<*const T>();
248
249 assert_impls_unwind_safe::<*mut T>();
250 assert_impls_ref_unwind_safe::<*mut T>();
251 }
252
253 #[test]
254 #[cfg(feature = "auto-traits")]
255 fn mut_ref_not_unwind_safe() {
256 assert!(impls!(&mut (): !UnwindSafe));
257 }
258}