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);