facet_core/impls_core/
pointer.rs

1use core::{fmt, hash::Hash};
2
3use crate::{
4    Facet, HasherProxy, MarkerTraits, PointerType, Shape, Type, TypeParam, ValuePointerType,
5    ValueVTable,
6};
7
8macro_rules! impl_facet_for_pointer {
9    ($variant:ident: $type:ty => $shape:expr => $vtable_builder:expr => $ptr_type:ident, $mutable:expr) => {
10        unsafe impl<'a, T: Facet<'a> + ?Sized> Facet<'a> for $type {
11            const VTABLE: &'static ValueVTable = &const {
12                $vtable_builder
13                    .type_name(|f, opts| {
14                        if let Some(opts) = opts.for_children() {
15                            if stringify!($ptr_type) == "Raw" {
16                                if $mutable {
17                                    write!(f, "*mut ")?;
18                                } else {
19                                    write!(f, "*const ")?;
20                                }
21                            } else {
22                                write!(f, "&")?;
23                                if $mutable {
24                                    write!(f, "mut ")?;
25                                }
26                            }
27                            (T::VTABLE.type_name)(f, opts)
28                        } else {
29                            if stringify!($ptr_type) == "Raw" {
30                                if $mutable {
31                                    write!(f, "*mut ⋯")
32                                } else {
33                                    write!(f, "*const ⋯")
34                                }
35                            } else {
36                                write!(f, "&")?;
37                                if $mutable {
38                                    write!(f, "mut ⋯")
39                                } else {
40                                    write!(f, "⋯")
41                                }
42                            }
43                        }
44                    })
45                    .build()
46            };
47
48            const SHAPE: &'static Shape<'static> = &const {
49                $shape
50                    .type_params(&[TypeParam {
51                        name: "T",
52                        shape: || T::SHAPE,
53                    }])
54                    .ty({
55                        let is_wide =
56                            ::core::mem::size_of::<$type>() != ::core::mem::size_of::<*const ()>();
57                        let vpt = ValuePointerType {
58                            mutable: $mutable,
59                            wide: is_wide,
60                            target: || T::SHAPE,
61                        };
62
63                        Type::Pointer(PointerType::$ptr_type(vpt))
64                    })
65                    .build()
66            };
67        }
68    };
69}
70
71// *const pointers
72impl_facet_for_pointer!(
73    Raw: *const T
74        => Shape::builder_for_sized::<Self>()
75            .inner(|| T::SHAPE)
76        => ValueVTable::builder::<Self>()
77            .marker_traits(
78                MarkerTraits::EQ
79                    .union(MarkerTraits::COPY)
80                    .union(MarkerTraits::UNPIN),
81            )
82            .debug(fmt::Debug::fmt)
83            .clone_into(|src, dst| unsafe { dst.put(*src) })
84            .eq(|left, right| left.cast::<()>().eq(&right.cast::<()>()))
85            .partial_ord(|&left, &right| {
86                left.cast::<()>().partial_cmp(&right.cast::<()>())
87            })
88            .ord(|&left, &right| left.cast::<()>().cmp(&right.cast::<()>()))
89            .hash(|value, hasher_this, hasher_write_fn| {
90                value.hash(&mut unsafe {
91                    HasherProxy::new(hasher_this, hasher_write_fn)
92                })
93            })
94        => Raw, false
95);
96
97// *mut pointers
98impl_facet_for_pointer!(
99    Raw: *mut T
100        => Shape::builder_for_sized::<Self>()
101            .inner(|| T::SHAPE)
102        => ValueVTable::builder::<Self>()
103            .marker_traits(
104                MarkerTraits::EQ
105                    .union(MarkerTraits::COPY)
106                    .union(MarkerTraits::UNPIN),
107            )
108            .debug(fmt::Debug::fmt)
109            .clone_into(|src, dst| unsafe { dst.put(*src) })
110            .eq(|left, right| left.cast::<()>().eq(&right.cast::<()>()))
111            .partial_ord(|&left, &right| {
112                left.cast::<()>().partial_cmp(&right.cast::<()>())
113            })
114            .ord(|&left, &right| left.cast::<()>().cmp(&right.cast::<()>()))
115            .hash(|value, hasher_this, hasher_write_fn| {
116                value.hash(&mut unsafe {
117                    HasherProxy::new(hasher_this, hasher_write_fn)
118                })
119            })
120        => Raw, true
121);
122
123// &T references
124impl_facet_for_pointer!(
125    Reference: &'a T
126        => Shape::builder_for_sized::<Self>()
127        => {
128            let mut marker_traits = MarkerTraits::COPY.union(MarkerTraits::UNPIN);
129            if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::EQ) {
130                marker_traits = marker_traits.union(MarkerTraits::EQ);
131            }
132            if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::SYNC) {
133                marker_traits = marker_traits.union(MarkerTraits::SEND).union(MarkerTraits::SYNC);
134            }
135
136            let mut builder = ValueVTable::builder::<Self>()
137                .marker_traits(marker_traits)
138                .clone_into(|src, dst| unsafe { dst.put(core::ptr::read(src)) });
139
140            // Forward trait methods to the underlying type if it implements them
141            if T::VTABLE.debug.is_some() {
142                builder = builder.debug(|value, f| {
143                    let target_ptr = crate::PtrConst::new(value);
144                    unsafe { (T::VTABLE.debug.unwrap())(target_ptr, f) }
145                });
146            }
147
148            if T::VTABLE.display.is_some() {
149                builder = builder.display(|value, f| {
150                    let target_ptr = crate::PtrConst::new(value);
151                    unsafe { (T::VTABLE.display.unwrap())(target_ptr, f) }
152                });
153            }
154
155            if T::VTABLE.eq.is_some() {
156                builder = builder.eq(|a, b| {
157                    let a_ptr = crate::PtrConst::new(a);
158                    let b_ptr = crate::PtrConst::new(b);
159                    unsafe { (T::VTABLE.eq.unwrap())(a_ptr, b_ptr) }
160                });
161            }
162
163            if T::VTABLE.partial_ord.is_some() {
164                builder = builder.partial_ord(|a, b| {
165                    let a_ptr = crate::PtrConst::new(a);
166                    let b_ptr = crate::PtrConst::new(b);
167                    unsafe { (T::VTABLE.partial_ord.unwrap())(a_ptr, b_ptr) }
168                });
169            }
170
171            if T::VTABLE.ord.is_some() {
172                builder = builder.ord(|a, b| {
173                    let a_ptr = crate::PtrConst::new(a);
174                    let b_ptr = crate::PtrConst::new(b);
175                    unsafe { (T::VTABLE.ord.unwrap())(a_ptr, b_ptr) }
176                });
177            }
178
179            if T::VTABLE.hash.is_some() {
180                builder = builder.hash(|value, hasher_this, hasher_write_fn| {
181                    let target_ptr = crate::PtrConst::new(value);
182                    unsafe { (T::VTABLE.hash.unwrap())(target_ptr, hasher_this, hasher_write_fn) }
183                });
184            }
185
186            builder
187        }
188        => Reference, false
189);
190
191// &mut T references
192impl_facet_for_pointer!(
193    Reference: &'a mut T
194        => Shape::builder_for_sized::<Self>()
195        => {
196            let mut marker_traits = MarkerTraits::UNPIN;
197            if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::EQ) {
198                marker_traits = marker_traits.union(MarkerTraits::EQ);
199            }
200            if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::SEND) {
201                marker_traits = marker_traits.union(MarkerTraits::SEND);
202            }
203            if T::SHAPE.vtable.marker_traits.contains(MarkerTraits::SYNC) {
204                marker_traits = marker_traits.union(MarkerTraits::SYNC);
205            }
206
207            let mut builder = ValueVTable::builder::<Self>()
208                .marker_traits(marker_traits);
209
210            // Forward trait methods to the underlying type if it implements them
211            if T::VTABLE.debug.is_some() {
212                builder = builder.debug(|value, f| {
213                    let target_ptr = crate::PtrConst::new(value);
214                    unsafe { (T::VTABLE.debug.unwrap())(target_ptr, f) }
215                });
216            }
217
218            if T::VTABLE.display.is_some() {
219                builder = builder.display(|value, f| {
220                    let target_ptr = crate::PtrConst::new(value);
221                    unsafe { (T::VTABLE.display.unwrap())(target_ptr, f) }
222                });
223            }
224
225            if T::VTABLE.eq.is_some() {
226                builder = builder.eq(|a, b| {
227                    let a_ptr = crate::PtrConst::new(a);
228                    let b_ptr = crate::PtrConst::new(b);
229                    unsafe { (T::VTABLE.eq.unwrap())(a_ptr, b_ptr) }
230                });
231            }
232
233            if T::VTABLE.partial_ord.is_some() {
234                builder = builder.partial_ord(|a, b| {
235                    let a_ptr = crate::PtrConst::new(a);
236                    let b_ptr = crate::PtrConst::new(b);
237                    unsafe { (T::VTABLE.partial_ord.unwrap())(a_ptr, b_ptr) }
238                });
239            }
240
241            if T::VTABLE.ord.is_some() {
242                builder = builder.ord(|a, b| {
243                    let a_ptr = crate::PtrConst::new(a);
244                    let b_ptr = crate::PtrConst::new(b);
245                    unsafe { (T::VTABLE.ord.unwrap())(a_ptr, b_ptr) }
246                });
247            }
248
249            if T::VTABLE.hash.is_some() {
250                builder = builder.hash(|value, hasher_this, hasher_write_fn| {
251                    let target_ptr = crate::PtrConst::new(value);
252                    unsafe { (T::VTABLE.hash.unwrap())(target_ptr, hasher_this, hasher_write_fn) }
253                });
254            }
255
256            builder
257        }
258        => Reference, true
259);