facet_core/impls_core/
reference.rs

1use core::fmt;
2
3use crate::{
4    Def, Facet, KnownPointer, MarkerTraits, PointerDef, PointerFlags, PointerType, PointerVTable,
5    PtrConst, PtrConstWide, Shape, Type, TypeParam, VTableView, ValuePointerType, ValueVTable,
6};
7
8macro_rules! impl_for_ref {
9    ($($modifiers:tt)*) => {
10        unsafe impl<'a, T: Facet<'a>> Facet<'a> for &'a $($modifiers)* T {
11            const VTABLE: &'static ValueVTable = &const {
12                ValueVTable::builder::<Self>()
13                    .marker_traits(|| {
14                        let mut marker_traits = if stringify!($($modifiers)*).is_empty() {
15                            MarkerTraits::COPY.union(MarkerTraits::UNPIN)
16                        } else {
17                            MarkerTraits::UNPIN
18                        };
19                        if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::EQ) {
20                            marker_traits = marker_traits.union(MarkerTraits::EQ);
21                        }
22                        if T::SHAPE.vtable.marker_traits().contains(MarkerTraits::SYNC) {
23                            marker_traits = marker_traits
24                                .union(MarkerTraits::SEND)
25                                .union(MarkerTraits::SYNC);
26                        }
27                        if T::SHAPE
28                            .vtable
29                            .marker_traits()
30                            .contains(MarkerTraits::REF_UNWIND_SAFE)
31                        {
32                            marker_traits = marker_traits.union(MarkerTraits::REF_UNWIND_SAFE);
33                            if stringify!($($modifiers)*).is_empty() {
34                                marker_traits = marker_traits.union(MarkerTraits::UNWIND_SAFE);
35                            }
36                        }
37
38                        marker_traits
39                    })
40                    .display(|| {
41                        if T::VTABLE.has_display() {
42                            Some(|value, f| {
43                                let view = VTableView::<T>::of();
44                                view.display().unwrap()(*value, f)
45                            })
46                        } else {
47                            None
48                        }
49                    })
50                    .debug(|| {
51                        if T::VTABLE.has_debug() {
52                            Some(|value, f| {
53                                let view = VTableView::<T>::of();
54                                view.debug().unwrap()(*value, f)
55                            })
56                        } else {
57                            None
58                        }
59                    })
60                    .clone_into(|| {
61                        if stringify!($($modifiers)*).is_empty() {
62                            Some(|src, dst| unsafe { dst.put(core::ptr::read(src)) })
63                        } else {
64                            None
65                        }
66                    })
67                    .type_name(|f, opts| {
68                        if stringify!($($modifiers)*).is_empty() {
69                            if let Some(opts) = opts.for_children() {
70                                write!(f, "&")?;
71                                (T::VTABLE.type_name())(f, opts)
72                            } else {
73                                write!(f, "&⋯")
74                            }
75                        } else {
76                            if let Some(opts) = opts.for_children() {
77                                write!(f, "&mut ")?;
78                                (T::VTABLE.type_name())(f, opts)
79                            } else {
80                                write!(f, "&mut ⋯")
81                            }
82                        }
83                    })
84                    .build()
85            };
86
87            const SHAPE: &'static Shape = &const {
88                Shape::builder_for_sized::<Self>()
89                    .type_identifier("&")
90                    .type_params(&[TypeParam {
91                        name: "T",
92                        shape: || T::SHAPE,
93                    }])
94                    .ty({
95                        let vpt = ValuePointerType {
96                            mutable: !stringify!($($modifiers)*).is_empty(),
97                            wide: false,
98                            target: || T::SHAPE,
99                        };
100
101                        Type::Pointer(PointerType::Reference(vpt))
102                    })
103                    .def(Def::Pointer(
104                        PointerDef::builder()
105                            .pointee(|| T::SHAPE)
106                            .flags(PointerFlags::EMPTY)
107                            .known(if stringify!($($modifiers)*).is_empty() {
108                                KnownPointer::SharedReference
109                            } else {
110                                KnownPointer::ExclusiveReference
111                            })
112                            .vtable(
113                                &const {
114                                    PointerVTable::builder()
115                                        .borrow_fn(|this| {
116                                            let ptr: && $($modifiers)* T = unsafe { this.get::<Self>() };
117                                            PtrConst::new(*ptr).into()
118                                        })
119                                        .build()
120                                },
121                            )
122                            .build(),
123                    ))
124                    .build()
125            };
126        }
127    };
128}
129
130impl_for_ref!();
131impl_for_ref!(mut);
132
133macro_rules! impl_for_string_ref {
134    ($($modifiers:tt)*) => {
135        unsafe impl<'a> Facet<'a> for &'a $($modifiers)* str {
136            const VTABLE: &'static ValueVTable = &const {
137                ValueVTable::builder::<Self>()
138                    .marker_traits(|| {
139                        let mut marker_traits = MarkerTraits::COPY.union(MarkerTraits::UNPIN);
140                        if str::SHAPE.vtable.marker_traits().contains(MarkerTraits::EQ) {
141                            marker_traits = marker_traits.union(MarkerTraits::EQ);
142                        }
143                        if str::SHAPE
144                            .vtable
145                            .marker_traits()
146                            .contains(MarkerTraits::SYNC)
147                        {
148                            marker_traits = marker_traits
149                                .union(MarkerTraits::SEND)
150                                .union(MarkerTraits::SYNC);
151                        }
152                        if str::SHAPE
153                            .vtable
154                            .marker_traits()
155                            .contains(MarkerTraits::REF_UNWIND_SAFE)
156                        {
157                            marker_traits = marker_traits
158                                .union(MarkerTraits::UNWIND_SAFE)
159                                .union(MarkerTraits::REF_UNWIND_SAFE);
160                        }
161
162                        marker_traits
163                    })
164                    .display(|| Some(fmt::Display::fmt))
165                    .debug(|| Some(fmt::Debug::fmt))
166                    .clone_into(|| {
167                        if stringify!($($modifiers)*).is_empty() {
168                            Some(|src, dst| unsafe { dst.put(core::ptr::read(src)) })
169                        } else {
170                            None
171                        }
172                    })
173                    .type_name(|f, _opts| {
174                        if stringify!($($modifiers)*).is_empty() {
175                            write!(f, "&str")
176                        } else {
177                            write!(f, "&mut str")
178                        }
179                    })
180                    .build()
181            };
182
183            const SHAPE: &'static Shape = &const {
184                Shape::builder_for_sized::<Self>()
185                    .type_identifier("&_")
186                    .type_params(&[TypeParam {
187                        name: "T",
188                        shape: || str::SHAPE,
189                    }])
190                    .ty({
191                        let vpt = ValuePointerType {
192                            mutable: !stringify!($($modifiers)*).is_empty(),
193                            wide: true, // string slices are always wide (fat pointers)
194                            target: || str::SHAPE,
195                        };
196
197                        Type::Pointer(PointerType::Reference(vpt))
198                    })
199                    .build()
200            };
201        }
202    };
203}
204
205impl_for_string_ref!();
206impl_for_string_ref!(mut);
207
208macro_rules! impl_for_slice_ref {
209    ($($modifiers:tt)*) => {
210        unsafe impl<'a, U: Facet<'a>> Facet<'a> for &'a $($modifiers)* [U] {
211            const VTABLE: &'static ValueVTable = &const {
212                ValueVTable::builder::<Self>()
213                    .marker_traits(|| {
214                        let mut marker_traits = MarkerTraits::COPY.union(MarkerTraits::UNPIN);
215                        if <[U]>::SHAPE
216                            .vtable
217                            .marker_traits()
218                            .contains(MarkerTraits::EQ)
219                        {
220                            marker_traits = marker_traits.union(MarkerTraits::EQ);
221                        }
222                        if <[U]>::SHAPE
223                            .vtable
224                            .marker_traits()
225                            .contains(MarkerTraits::SYNC)
226                        {
227                            marker_traits = marker_traits
228                                .union(MarkerTraits::SEND)
229                                .union(MarkerTraits::SYNC);
230                        }
231                        if <[U]>::SHAPE
232                            .vtable
233                            .marker_traits()
234                            .contains(MarkerTraits::REF_UNWIND_SAFE)
235                        {
236                            marker_traits = marker_traits
237                                .union(MarkerTraits::UNWIND_SAFE)
238                                .union(MarkerTraits::REF_UNWIND_SAFE);
239                        }
240
241                        marker_traits
242                    })
243                    .debug(|| {
244                        if <[U]>::VTABLE.has_debug() {
245                            Some(|value, f| {
246                                let view = VTableView::<[U]>::of();
247                                view.debug().unwrap()(*value, f)
248                            })
249                        } else {
250                            None
251                        }
252                    })
253                    .clone_into(|| Some(|src, dst| unsafe { dst.put(core::ptr::read(src)) }))
254                    .type_name(|f, opts| {
255                        if stringify!($($modifiers)*).is_empty() {
256                            if let Some(opts) = opts.for_children() {
257                                write!(f, "&[")?;
258                                (<U>::VTABLE.type_name())(f, opts)?;
259                                write!(f, "]")
260                            } else {
261                                write!(f, "&⋯")
262                            }
263                        } else {
264                            if let Some(opts) = opts.for_children() {
265                                write!(f, "&mut [")?;
266                                (<U>::VTABLE.type_name())(f, opts)?;
267                                write!(f, "]")
268                            } else {
269                                write!(f, "&mut ⋯")
270                            }
271                        }
272                    })
273                    .build()
274            };
275
276            const SHAPE: &'static Shape = &const {
277                Shape::builder_for_sized::<Self>()
278                    .type_identifier("&[_]")
279                    .type_params(&[TypeParam {
280                        name: "T",
281                        shape: || <[U]>::SHAPE,
282                    }])
283                    .ty({
284                        let vpt = ValuePointerType {
285                            mutable: !stringify!($($modifiers)*).is_empty(),
286                            wide: true, // slice references are always wide (fat pointers)
287                            target: || <[U]>::SHAPE,
288                        };
289
290                        Type::Pointer(PointerType::Reference(vpt))
291                    })
292                    .def(Def::Pointer(
293                        PointerDef::builder()
294                            .pointee(|| <[U]>::SHAPE)
295                            .flags(PointerFlags::EMPTY)
296                            .known(if stringify!($($modifiers)*).is_empty() {
297                                KnownPointer::SharedReference
298                            } else {
299                                KnownPointer::ExclusiveReference
300                            })
301                            .vtable(
302                                &const {
303                                    PointerVTable::builder()
304                                        .borrow_fn(|this| {
305                                            // `this` is a PtrConst pointing to our slice reference (&[U] or &mut [U])
306                                            // We get a reference to our slice reference, so we have &&[U] or &&mut [U]
307                                            let ptr: && $($modifiers)* [U] = unsafe { this.get::<Self>() };
308
309                                            // Dereference once to get the actual slice reference: &[U] or &mut [U]
310                                            // This is the wide pointer we want to return (contains ptr + length)
311                                            // Note: Even for &mut [U], we can coerce to &[U] for borrowing
312                                            let s: &[U] = *ptr;
313
314                                            // Convert the slice reference to a raw pointer (*const [U])
315                                            // The &raw const operator creates a raw pointer from a place expression
316                                            // without going through a reference first, preserving the wide pointer
317                                            PtrConstWide::new(&raw const *s).into()
318                                        })
319                                        .build()
320                                },
321                            )
322                            .build(),
323                    ))
324                    .build()
325            };
326        }
327    };
328}
329
330impl_for_slice_ref!();
331impl_for_slice_ref!(mut);