1use core::ptr::NonNull;
2
3use alloc::boxed::Box;
4use alloc::rc::{Rc, Weak};
5use alloc::vec::Vec;
6
7use crate::shape_util::vtable_builder_for_ptr;
8use crate::{
9 Def, Facet, KnownPointer, PointerDef, PointerFlags, PointerVTable, PtrConst, PtrMut, PtrUninit,
10 Shape, SliceBuilderVTable, TryBorrowInnerError, TryFromError, TryIntoInnerError, Type,
11 UserType, value_vtable,
12};
13
14unsafe impl<'a, T: Facet<'a>> Facet<'a> for Rc<T> {
15 const SHAPE: &'static crate::Shape = &const {
16 crate::Shape::builder_for_sized::<Self>()
17 .vtable({
18 unsafe fn try_from<'a, 'src, 'dst, T: Facet<'a>>(
20 src_ptr: PtrConst<'src>,
21 src_shape: &'static Shape,
22 dst: PtrUninit<'dst>,
23 ) -> Result<PtrMut<'dst>, TryFromError> {
24 if src_shape.id != T::SHAPE.id {
25 return Err(TryFromError::UnsupportedSourceShape {
26 src_shape,
27 expected: &[T::SHAPE],
28 });
29 }
30 let t = unsafe { src_ptr.read::<T>() };
31 let rc = Rc::new(t);
32 Ok(unsafe { dst.put(rc) })
33 }
34
35 unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
36 src_ptr: PtrMut<'src>,
37 dst: PtrUninit<'dst>,
38 ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
39 let rc = unsafe { src_ptr.get::<Rc<T>>() };
40 match Rc::try_unwrap(rc.clone()) {
41 Ok(t) => Ok(unsafe { dst.put(t) }),
42 Err(_) => Err(TryIntoInnerError::Unavailable),
43 }
44 }
45
46 unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
47 src_ptr: PtrConst<'src>,
48 ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
49 let rc = unsafe { src_ptr.get::<Rc<T>>() };
50 Ok(PtrConst::new(NonNull::from(&**rc)))
51 }
52
53 let mut vtable = vtable_builder_for_ptr::<T, Self>()
54 .type_name(|f, opts| {
55 write!(f, "{}<", Self::SHAPE.type_identifier)?;
56 if let Some(opts) = opts.for_children() {
57 (T::SHAPE.vtable.type_name())(f, opts)?;
58 } else {
59 write!(f, "…")?;
60 }
61 write!(f, ">")?;
62 Ok(())
63 })
64 .build();
65
66 {
67 vtable.try_from = Some(try_from::<T>);
68 vtable.try_into_inner = Some(try_into_inner::<T>);
69 vtable.try_borrow_inner = Some(try_borrow_inner::<T>);
70 }
71 vtable
72 })
73 .type_identifier("Rc")
74 .type_params(&[crate::TypeParam {
75 name: "T",
76 shape: T::SHAPE,
77 }])
78 .ty(Type::User(UserType::Opaque))
79 .def(Def::Pointer(
80 PointerDef::builder()
81 .pointee(T::SHAPE)
82 .flags(PointerFlags::EMPTY)
83 .known(KnownPointer::Rc)
84 .weak(|| <Weak<T> as Facet>::SHAPE)
85 .vtable(
86 &const {
87 PointerVTable::builder()
88 .borrow_fn(|this| {
89 let ptr = Self::as_ptr(unsafe { this.get() });
90 PtrConst::new(unsafe { NonNull::new_unchecked(ptr as *mut T) })
91 })
92 .new_into_fn(|this, ptr| {
93 let t = unsafe { ptr.read::<T>() };
94 let rc = Rc::new(t);
95 unsafe { this.put(rc) }
96 })
97 .downgrade_into_fn(|strong, weak| unsafe {
98 weak.put(Rc::downgrade(strong.get::<Self>()))
99 })
100 .build()
101 },
102 )
103 .build(),
104 ))
105 .inner(T::SHAPE)
106 .build()
107 };
108}
109
110unsafe impl<'a> Facet<'a> for Rc<str> {
111 const SHAPE: &'static crate::Shape = &const {
112 crate::Shape::builder_for_sized::<Self>()
113 .vtable({
114 vtable_builder_for_ptr::<str, Self>()
115 .type_name(|f, opts| {
116 write!(f, "{}", Self::SHAPE.type_identifier)?;
117 if let Some(opts) = opts.for_children() {
118 write!(f, "<")?;
119 (str::SHAPE.vtable.type_name())(f, opts)?;
120 write!(f, ">")?;
121 } else {
122 write!(f, "<…>")?;
123 }
124 Ok(())
125 })
126 .build()
127 })
128 .type_identifier("Rc")
129 .type_params(&[crate::TypeParam {
130 name: "T",
131 shape: str::SHAPE,
132 }])
133 .ty(Type::User(UserType::Opaque))
134 .def(Def::Pointer(
135 PointerDef::builder()
136 .pointee(str::SHAPE)
137 .flags(PointerFlags::EMPTY)
138 .known(KnownPointer::Rc)
139 .weak(|| <Weak<str> as Facet>::SHAPE)
140 .vtable(
141 &const {
142 PointerVTable::builder()
143 .borrow_fn(|this| unsafe {
144 let concrete = this.get::<Rc<str>>();
145 let s: &str = concrete;
146 PtrConst::new(NonNull::from(s))
147 })
148 .downgrade_into_fn(|strong, weak| unsafe {
149 weak.put(Rc::downgrade(strong.get::<Self>()))
150 })
151 .build()
152 },
153 )
154 .build(),
155 ))
156 .inner(str::SHAPE)
157 .build()
158 };
159}
160
161unsafe impl<'a, U: Facet<'a>> Facet<'a> for Rc<[U]> {
162 const SHAPE: &'static crate::Shape = &const {
163 fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut<'static> {
164 let v = Box::new(Vec::<U>::new());
165 let raw = Box::into_raw(v);
166 PtrMut::new(unsafe { NonNull::new_unchecked(raw) })
167 }
168
169 fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
170 unsafe {
171 let vec = builder.as_mut::<Vec<U>>();
172 let value = item.read::<U>();
173 vec.push(value);
174 }
175 }
176
177 fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut<'static>) -> PtrConst<'static> {
178 unsafe {
179 let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
180 let arc: Rc<[U]> = (*vec_box).into();
181 let arc_box = Box::new(arc);
182 PtrConst::new(NonNull::new_unchecked(Box::into_raw(arc_box)))
183 }
184 }
185
186 fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut<'static>) {
187 unsafe {
188 let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
189 }
190 }
191
192 crate::Shape::builder_for_sized::<Self>()
193 .vtable({
194 vtable_builder_for_ptr::<[U], Self>()
195 .type_name(|f, opts| {
196 write!(f, "{}", Self::SHAPE.type_identifier)?;
197 if let Some(opts) = opts.for_children() {
198 write!(f, "<")?;
199 (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
200 write!(f, ">")?;
201 } else {
202 write!(f, "<…>")?;
203 }
204 Ok(())
205 })
206 .build()
207 })
208 .type_identifier("Rc")
209 .type_params(&[crate::TypeParam {
210 name: "T",
211 shape: <[U]>::SHAPE,
212 }])
213 .ty(Type::User(UserType::Opaque))
214 .def(Def::Pointer(
215 PointerDef::builder()
216 .pointee(<[U]>::SHAPE)
217 .flags(PointerFlags::EMPTY)
218 .known(KnownPointer::Rc)
219 .weak(|| <Weak<[U]> as Facet>::SHAPE)
220 .vtable(
221 &const {
222 PointerVTable::builder()
223 .borrow_fn(|this| unsafe {
224 let concrete = this.get::<Rc<[U]>>();
225 let s: &[U] = concrete;
226 PtrConst::new(NonNull::from(s))
227 })
228 .downgrade_into_fn(|strong, weak| unsafe {
229 weak.put(Rc::downgrade(strong.get::<Self>()))
230 })
231 .slice_builder_vtable(
232 &const {
233 SliceBuilderVTable::builder()
234 .new_fn(slice_builder_new::<U>)
235 .push_fn(slice_builder_push::<U>)
236 .convert_fn(slice_builder_convert::<U>)
237 .free_fn(slice_builder_free::<U>)
238 .build()
239 },
240 )
241 .build()
242 },
243 )
244 .build(),
245 ))
246 .inner(<[U]>::SHAPE)
247 .build()
248 };
249}
250
251unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
252 const SHAPE: &'static crate::Shape = &const {
253 crate::Shape::builder_for_sized::<Self>()
254 .vtable({
255 value_vtable!(alloc::rc::Weak<T>, |f, opts| {
256 write!(f, "{}", Self::SHAPE.type_identifier)?;
257 if let Some(opts) = opts.for_children() {
258 write!(f, "<")?;
259 T::SHAPE.vtable.type_name()(f, opts)?;
260 write!(f, ">")?;
261 } else {
262 write!(f, "<…>")?;
263 }
264 Ok(())
265 })
266 })
267 .type_identifier("Weak")
268 .type_params(&[crate::TypeParam {
269 name: "T",
270 shape: T::SHAPE,
271 }])
272 .ty(Type::User(UserType::Opaque))
273 .def(Def::Pointer(
274 PointerDef::builder()
275 .pointee(T::SHAPE)
276 .flags(PointerFlags::WEAK)
277 .known(KnownPointer::RcWeak)
278 .strong(<Rc<T> as Facet>::SHAPE)
279 .vtable(
280 &const {
281 PointerVTable::builder()
282 .upgrade_into_fn(|weak, strong| unsafe {
283 Some(strong.put(weak.get::<Self>().upgrade()?))
284 })
285 .build()
286 },
287 )
288 .build(),
289 ))
290 .inner(T::SHAPE)
291 .build()
292 };
293}
294
295unsafe impl<'a> Facet<'a> for Weak<str> {
296 const SHAPE: &'static crate::Shape = &const {
297 crate::Shape::builder_for_sized::<Self>()
298 .vtable({
299 value_vtable!(alloc::rc::Weak<str>, |f, opts| {
300 write!(f, "{}", Self::SHAPE.type_identifier)?;
301 if let Some(opts) = opts.for_children() {
302 write!(f, "<")?;
303 (str::SHAPE.vtable.type_name())(f, opts)?;
304 write!(f, ">")?;
305 } else {
306 write!(f, "<…>")?;
307 }
308 Ok(())
309 })
310 })
311 .type_identifier("Weak")
312 .type_params(&[crate::TypeParam {
313 name: "T",
314 shape: str::SHAPE,
315 }])
316 .ty(Type::User(UserType::Opaque))
317 .def(Def::Pointer(
318 PointerDef::builder()
319 .pointee(str::SHAPE)
320 .flags(PointerFlags::WEAK)
321 .known(KnownPointer::RcWeak)
322 .strong(<Rc<str> as Facet>::SHAPE)
323 .vtable(
324 &const {
325 PointerVTable::builder()
326 .upgrade_into_fn(|weak, strong| unsafe {
327 Some(strong.put(weak.get::<Self>().upgrade()?))
328 })
329 .build()
330 },
331 )
332 .build(),
333 ))
334 .inner(str::SHAPE)
335 .build()
336 };
337}
338
339unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
340 const SHAPE: &'static crate::Shape = &const {
341 crate::Shape::builder_for_sized::<Self>()
342 .vtable({
343 value_vtable!(alloc::rc::Weak<[U]>, |f, opts| {
344 write!(f, "{}", Self::SHAPE.type_identifier)?;
345 if let Some(opts) = opts.for_children() {
346 write!(f, "<")?;
347 (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
348 write!(f, ">")?;
349 } else {
350 write!(f, "<…>")?;
351 }
352 Ok(())
353 })
354 })
355 .type_identifier("Weak")
356 .type_params(&[crate::TypeParam {
357 name: "T",
358 shape: <[U]>::SHAPE,
359 }])
360 .ty(Type::User(UserType::Opaque))
361 .def(Def::Pointer(
362 PointerDef::builder()
363 .pointee(<[U]>::SHAPE)
364 .flags(PointerFlags::WEAK)
365 .known(KnownPointer::RcWeak)
366 .strong(<Rc<[U]> as Facet>::SHAPE)
367 .vtable(
368 &const {
369 PointerVTable::builder()
370 .upgrade_into_fn(|weak, strong| unsafe {
371 Some(strong.put(weak.get::<Self>().upgrade()?))
372 })
373 .build()
374 },
375 )
376 .build(),
377 ))
378 .inner(<[U]>::SHAPE)
379 .build()
380 };
381}
382
383#[cfg(test)]
384mod tests {
385 use core::mem::ManuallyDrop;
386
387 use alloc::rc::{Rc, Weak as RcWeak};
388 use alloc::string::String;
389
390 use super::*;
391
392 #[test]
393 fn test_rc_type_params() {
394 let [type_param_1] = <Rc<i32>>::SHAPE.type_params else {
395 panic!("Rc<T> should only have 1 type param")
396 };
397 assert_eq!(type_param_1.shape(), i32::SHAPE);
398 }
399
400 #[test]
401 fn test_rc_vtable_1_new_borrow_drop() {
402 facet_testhelpers::setup();
403
404 let rc_shape = <Rc<String>>::SHAPE;
405 let rc_def = rc_shape
406 .def
407 .into_pointer()
408 .expect("Rc<T> should have a smart pointer definition");
409
410 let rc_uninit_ptr = rc_shape.allocate().unwrap();
412
413 let new_into_fn = rc_def
415 .vtable
416 .new_into_fn
417 .expect("Rc<T> should have new_into_fn");
418
419 let mut value = ManuallyDrop::new(String::from("example"));
421 let rc_ptr = unsafe { new_into_fn(rc_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
422
423 let borrow_fn = rc_def
425 .vtable
426 .borrow_fn
427 .expect("Rc<T> should have borrow_fn");
428
429 let borrowed_ptr = unsafe { borrow_fn(rc_ptr.as_const()) };
431 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
433
434 let drop_fn = rc_shape
436 .vtable
437 .drop_in_place
438 .expect("Rc<T> should have drop_in_place");
439
440 unsafe { drop_fn(rc_ptr) };
443
444 unsafe { rc_shape.deallocate_mut(rc_ptr).unwrap() };
447 }
448
449 #[test]
450 fn test_rc_vtable_2_downgrade_upgrade_drop() {
451 facet_testhelpers::setup();
452
453 let rc_shape = <Rc<String>>::SHAPE;
454 let rc_def = rc_shape
455 .def
456 .into_pointer()
457 .expect("Rc<T> should have a smart pointer definition");
458
459 let weak_shape = <RcWeak<String>>::SHAPE;
460 let weak_def = weak_shape
461 .def
462 .into_pointer()
463 .expect("RcWeak<T> should have a smart pointer definition");
464
465 let rc1_uninit_ptr = rc_shape.allocate().unwrap();
467 let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
468 let mut value = ManuallyDrop::new(String::from("example"));
469 let rc1_ptr =
470 unsafe { new_into_fn(rc1_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
471
472 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
474 let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
475 let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
477
478 let rc2_uninit_ptr = rc_shape.allocate().unwrap();
480 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
481 let rc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) }
484 .expect("Upgrade should succeed while original Rc exists");
485
486 let borrow_fn = rc_def.vtable.borrow_fn.unwrap();
488 let borrowed_ptr = unsafe { borrow_fn(rc2_ptr.as_const()) };
490 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
492
493 let rc_drop_fn = rc_shape.vtable.drop_in_place.unwrap();
495 let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
496
497 unsafe {
498 rc_drop_fn(rc1_ptr);
500 rc_shape.deallocate_mut(rc1_ptr).unwrap();
501 rc_drop_fn(rc2_ptr);
502 rc_shape.deallocate_mut(rc2_ptr).unwrap();
503
504 weak_drop_fn(weak1_ptr);
506 weak_shape.deallocate_mut(weak1_ptr).unwrap();
507 }
508 }
509
510 #[test]
511 fn test_rc_vtable_3_downgrade_drop_try_upgrade() {
512 facet_testhelpers::setup();
513
514 let rc_shape = <Rc<String>>::SHAPE;
515 let rc_def = rc_shape
516 .def
517 .into_pointer()
518 .expect("Rc<T> should have a smart pointer definition");
519
520 let weak_shape = <RcWeak<String>>::SHAPE;
521 let weak_def = weak_shape
522 .def
523 .into_pointer()
524 .expect("RcWeak<T> should have a smart pointer definition");
525
526 let rc1_uninit_ptr = rc_shape.allocate().unwrap();
528 let new_into_fn = rc_def.vtable.new_into_fn.unwrap();
529 let mut value = ManuallyDrop::new(String::from("example"));
530 let rc1_ptr =
531 unsafe { new_into_fn(rc1_uninit_ptr, PtrMut::new(NonNull::from(&mut value))) };
532
533 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
535 let downgrade_into_fn = rc_def.vtable.downgrade_into_fn.unwrap();
536 let weak1_ptr = unsafe { downgrade_into_fn(rc1_ptr, weak1_uninit_ptr) };
538
539 let rc_drop_fn = rc_shape.vtable.drop_in_place.unwrap();
541 unsafe {
542 rc_drop_fn(rc1_ptr);
543 rc_shape.deallocate_mut(rc1_ptr).unwrap();
544 }
545
546 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
548 let rc2_uninit_ptr = rc_shape.allocate().unwrap();
549 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, rc2_uninit_ptr) };
551
552 assert!(
554 upgrade_result.is_none(),
555 "Upgrade should fail after the strong Rc is dropped"
556 );
557
558 let weak_drop_fn = weak_shape.vtable.drop_in_place.unwrap();
560 unsafe {
561 rc_shape.deallocate_uninit(rc2_uninit_ptr).unwrap();
563
564 weak_drop_fn(weak1_ptr);
566 weak_shape.deallocate_mut(weak1_ptr).unwrap();
567 }
568 }
569}