facet_core/impls_core/
reference.rs

1use crate::{
2    Def, Facet, KnownPointer, MarkerTraits, PointerDef, PointerFlags, PointerType, PointerVTable,
3    PtrConst, Shape, Type, TypeParam, VTableView, ValuePointerType, ValueVTable,
4};
5
6macro_rules! impl_for_ref {
7    ($($modifiers:tt)*) => {
8        unsafe impl<'a, T: ?Sized + Facet<'a>> Facet<'a> for &'a $($modifiers)* T {
9            const SHAPE: &'static Shape = &const {
10                Shape::builder_for_sized::<Self>()
11                    .vtable(
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::SHAPE.vtable.has_display() {
42                                    Some(|value, f| {
43                                        let view = VTableView::<T>::of();
44                                        view.display().unwrap()((&**value.get()).into(), f)
45                                    })
46                                } else {
47                                    None
48                                }
49                            })
50                            .debug({
51                                if T::SHAPE.vtable.has_debug() {
52                                    Some(|value, f| {
53                                        let view = VTableView::<T>::of();
54                                        view.debug().unwrap()((&**value.get()).into(), f)
55                                    })
56                                } else {
57                                    None
58                                }
59                            })
60                            .hash({
61                                if T::SHAPE.vtable.has_hash() {
62                                    Some(|value, hasher| {
63                                        let view = VTableView::<T>::of();
64                                        view.hash().unwrap()((&**value.get()).into(), hasher)
65                                    })
66                                } else {
67                                    None
68                                }
69                            })
70                            .partial_eq({
71                                if T::SHAPE.vtable.has_partial_eq() {
72                                    Some(|a, b| {
73                                        let view = VTableView::<T>::of();
74                                        view.partial_eq().unwrap()((&**a.get()).into(), (&**b.get()).into())
75                                    })
76                                } else {
77                                    None
78                                }
79                            })
80                            .partial_ord({
81                                if T::SHAPE.vtable.has_partial_ord() {
82                                    Some(|a, b| {
83                                        let view = VTableView::<T>::of();
84                                        view.partial_ord().unwrap()((&**a.get()).into(), (&**b.get()).into())
85                                    })
86                                } else {
87                                    None
88                                }
89                            })
90                            .ord({
91                                if T::SHAPE.vtable.has_ord() {
92                                    Some(|a, b| {
93                                        let view = VTableView::<T>::of();
94                                        view.ord().unwrap()((&**a.get()).into(), (&**b.get()).into())
95                                    })
96                                } else {
97                                    None
98                                }
99                            })
100                            .clone_into({
101                                if stringify!($($modifiers)*).is_empty() {
102                                    Some(|src, dst| unsafe { dst.put(core::ptr::read(src.as_ptr())).into() })
103                                } else {
104                                    None
105                                }
106                            })
107                            .type_name(|f, opts| {
108                                if stringify!($($modifiers)*).is_empty() {
109                                    if let Some(opts) = opts.for_children() {
110                                        write!(f, "&")?;
111                                        (T::SHAPE.vtable.type_name())(f, opts)
112                                    } else {
113                                        write!(f, "&…")
114                                    }
115                                } else {
116                                    if let Some(opts) = opts.for_children() {
117                                        write!(f, "&mut ")?;
118                                        (T::SHAPE.vtable.type_name())(f, opts)
119                                    } else {
120                                        write!(f, "&mut …")
121                                    }
122                                }
123                            })
124                            .build()
125                    )
126                    .type_identifier("&")
127                    .type_params(&[TypeParam {
128                        name: "T",
129                        shape: T::SHAPE,
130                    }])
131                    .ty({
132                        let vpt = ValuePointerType {
133                            mutable: !stringify!($($modifiers)*).is_empty(),
134                            wide: size_of::<*const T>() != size_of::<*const ()>(),
135                            target: T::SHAPE,
136                        };
137
138                        Type::Pointer(PointerType::Reference(vpt))
139                    })
140                    .def(Def::Pointer(
141                        PointerDef::builder()
142                            .pointee(T::SHAPE)
143                            .flags(PointerFlags::EMPTY)
144                            .known(if stringify!($($modifiers)*).is_empty() {
145                                KnownPointer::SharedReference
146                            } else {
147                                KnownPointer::ExclusiveReference
148                            })
149                            .vtable(
150                                &const {
151                                    PointerVTable::builder()
152                                        .borrow_fn(|this| {
153                                            let ptr: && $($modifiers)* T = unsafe { this.get::<Self>() };
154                                            let ptr: &T = *ptr;
155                                            PtrConst::new(core::ptr::NonNull::from(ptr)).into()
156                                        })
157                                        .build()
158                                },
159                            )
160                            .build(),
161                    ))
162                    .build()
163            };
164        }
165    };
166}
167
168impl_for_ref!();
169impl_for_ref!(mut);