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 parse_bytes: None,
132 try_from: None,
133 try_into_inner: None,
134 try_borrow_inner: None,
135 partial_eq: Some(const_ptr_partial_eq::<T>),
136 partial_cmp: Some(const_ptr_partial_cmp::<T>),
137 cmp: Some(const_ptr_cmp::<T>),
138 }
139 }
140
141 const fn build_const_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
142 TypeOpsIndirect {
143 drop_in_place: const_ptr_drop::<T>,
144 default_in_place: None,
145 clone_into: Some(const_ptr_clone::<T>),
146 is_truthy: None,
147 }
148 }
149
150 ShapeBuilder::for_sized::<*const T>("*const T")
151 .ty({
152 let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
153 let vpt = ValuePointerType {
154 mutable: false,
155 wide: is_wide,
156 target: T::SHAPE,
157 };
158 Type::Pointer(PointerType::Raw(vpt))
159 })
160 .def(Def::Scalar)
161 .type_params(&[TypeParam {
162 name: "T",
163 shape: T::SHAPE,
164 }])
165 .inner(T::SHAPE)
166 .vtable_indirect(&const { build_const_ptr_vtable::<T>() })
167 .type_ops_indirect(&const { build_const_ptr_type_ops::<T>() })
168 .eq()
169 .copy()
170 .build()
171 };
172}
173
174unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for *mut T {
176 const SHAPE: &'static Shape = &const {
177 const fn build_mut_ptr_vtable<'a, T: Facet<'a> + ?Sized>() -> VTableIndirect {
178 VTableIndirect {
179 display: None,
180 debug: Some(mut_ptr_debug::<T>),
181 hash: Some(mut_ptr_hash::<T>),
182 invariants: None,
183 parse: None,
184 parse_bytes: None,
185 try_from: None,
186 try_into_inner: None,
187 try_borrow_inner: None,
188 partial_eq: Some(mut_ptr_partial_eq::<T>),
189 partial_cmp: Some(mut_ptr_partial_cmp::<T>),
190 cmp: Some(mut_ptr_cmp::<T>),
191 }
192 }
193
194 const fn build_mut_ptr_type_ops<T: ?Sized>() -> TypeOpsIndirect {
195 TypeOpsIndirect {
196 drop_in_place: mut_ptr_drop::<T>,
197 default_in_place: None,
198 clone_into: Some(mut_ptr_clone::<T>),
199 is_truthy: None,
200 }
201 }
202
203 ShapeBuilder::for_sized::<*mut T>("*mut T")
204 .ty({
205 let is_wide = ::core::mem::size_of::<Self>() != ::core::mem::size_of::<*const ()>();
206 let vpt = ValuePointerType {
207 mutable: true,
208 wide: is_wide,
209 target: T::SHAPE,
210 };
211 Type::Pointer(PointerType::Raw(vpt))
212 })
213 .def(Def::Scalar)
214 .type_params(&[TypeParam {
215 name: "T",
216 shape: T::SHAPE,
217 }])
218 .inner(T::SHAPE)
219 .vtable_indirect(&const { build_mut_ptr_vtable::<T>() })
220 .type_ops_indirect(&const { build_mut_ptr_type_ops::<T>() })
221 .variance(Variance::INVARIANT)
223 .eq()
224 .copy()
225 .build()
226 };
227}
228
229#[cfg(test)]
230mod test {
231 use core::panic::{RefUnwindSafe, UnwindSafe};
232
233 #[cfg(feature = "auto-traits")]
234 use impls::impls;
235
236 #[allow(unused)]
237 const fn assert_impls_unwind_safe<T: UnwindSafe>() {}
238 #[allow(unused)]
239 const fn assert_impls_ref_unwind_safe<T: RefUnwindSafe>() {}
240
241 #[allow(unused)]
242 const fn ref_unwind_safe<T: RefUnwindSafe>() {
243 assert_impls_unwind_safe::<&T>();
244 assert_impls_ref_unwind_safe::<&T>();
245
246 assert_impls_ref_unwind_safe::<&mut T>();
247
248 assert_impls_unwind_safe::<*const T>();
249 assert_impls_ref_unwind_safe::<*const T>();
250
251 assert_impls_unwind_safe::<*mut T>();
252 assert_impls_ref_unwind_safe::<*mut T>();
253 }
254
255 #[test]
256 #[cfg(feature = "auto-traits")]
257 fn mut_ref_not_unwind_safe() {
258 assert!(impls!(&mut (): !UnwindSafe));
259 }
260}