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 builder = ValueVTable::builder::<Self>()
129                .marker_traits(
130                    MarkerTraits::UNPIN
131                        .union(MarkerTraits::COPY)
132                )
133                .clone_into(|src, dst| unsafe { dst.put(core::ptr::read(src)) });
134
135            // Forward trait methods to the underlying type if it implements them
136            if T::VTABLE.debug.is_some() {
137                builder = builder.debug(|value, f| {
138                    let target_ptr = crate::PtrConst::new(value);
139                    unsafe { (T::VTABLE.debug.unwrap())(target_ptr, f) }
140                });
141            }
142
143            if T::VTABLE.display.is_some() {
144                builder = builder.display(|value, f| {
145                    let target_ptr = crate::PtrConst::new(value);
146                    unsafe { (T::VTABLE.display.unwrap())(target_ptr, f) }
147                });
148            }
149
150            if T::VTABLE.eq.is_some() {
151                builder = builder.eq(|a, b| {
152                    let a_ptr = crate::PtrConst::new(a);
153                    let b_ptr = crate::PtrConst::new(b);
154                    unsafe { (T::VTABLE.eq.unwrap())(a_ptr, b_ptr) }
155                });
156            }
157
158            if T::VTABLE.partial_ord.is_some() {
159                builder = builder.partial_ord(|a, b| {
160                    let a_ptr = crate::PtrConst::new(a);
161                    let b_ptr = crate::PtrConst::new(b);
162                    unsafe { (T::VTABLE.partial_ord.unwrap())(a_ptr, b_ptr) }
163                });
164            }
165
166            if T::VTABLE.ord.is_some() {
167                builder = builder.ord(|a, b| {
168                    let a_ptr = crate::PtrConst::new(a);
169                    let b_ptr = crate::PtrConst::new(b);
170                    unsafe { (T::VTABLE.ord.unwrap())(a_ptr, b_ptr) }
171                });
172            }
173
174            if T::VTABLE.hash.is_some() {
175                builder = builder.hash(|value, hasher_this, hasher_write_fn| {
176                    let target_ptr = crate::PtrConst::new(value);
177                    unsafe { (T::VTABLE.hash.unwrap())(target_ptr, hasher_this, hasher_write_fn) }
178                });
179            }
180
181            builder
182        }
183        => Reference, false
184);
185
186// &mut T references
187impl_facet_for_pointer!(
188    Reference: &'a mut T
189        => Shape::builder_for_sized::<Self>()
190        => {
191            let mut builder = ValueVTable::builder::<Self>()
192                .marker_traits(
193                    MarkerTraits::UNPIN
194                );
195
196            // Forward trait methods to the underlying type if it implements them
197            if T::VTABLE.debug.is_some() {
198                builder = builder.debug(|value, f| {
199                    let target_ptr = crate::PtrConst::new(value);
200                    unsafe { (T::VTABLE.debug.unwrap())(target_ptr, f) }
201                });
202            }
203
204            if T::VTABLE.display.is_some() {
205                builder = builder.display(|value, f| {
206                    let target_ptr = crate::PtrConst::new(value);
207                    unsafe { (T::VTABLE.display.unwrap())(target_ptr, f) }
208                });
209            }
210
211            if T::VTABLE.eq.is_some() {
212                builder = builder.eq(|a, b| {
213                    let a_ptr = crate::PtrConst::new(a);
214                    let b_ptr = crate::PtrConst::new(b);
215                    unsafe { (T::VTABLE.eq.unwrap())(a_ptr, b_ptr) }
216                });
217            }
218
219            if T::VTABLE.partial_ord.is_some() {
220                builder = builder.partial_ord(|a, b| {
221                    let a_ptr = crate::PtrConst::new(a);
222                    let b_ptr = crate::PtrConst::new(b);
223                    unsafe { (T::VTABLE.partial_ord.unwrap())(a_ptr, b_ptr) }
224                });
225            }
226
227            if T::VTABLE.ord.is_some() {
228                builder = builder.ord(|a, b| {
229                    let a_ptr = crate::PtrConst::new(a);
230                    let b_ptr = crate::PtrConst::new(b);
231                    unsafe { (T::VTABLE.ord.unwrap())(a_ptr, b_ptr) }
232                });
233            }
234
235            if T::VTABLE.hash.is_some() {
236                builder = builder.hash(|value, hasher_this, hasher_write_fn| {
237                    let target_ptr = crate::PtrConst::new(value);
238                    unsafe { (T::VTABLE.hash.unwrap())(target_ptr, hasher_this, hasher_write_fn) }
239                });
240            }
241
242            builder
243        }
244        => Reference, true
245);