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