1use core::ptr::NonNull;
2
3use alloc::boxed::Box;
4use alloc::sync::{Arc, Weak};
5use alloc::vec::Vec;
6
7use crate::{
8 Def, Facet, KnownPointer, OxPtrConst, OxPtrMut, PointerDef, PointerFlags, PointerVTable,
9 PtrConst, PtrMut, PtrUninit, ShapeBuilder, SliceBuilderVTable, Type, TypeNameOpts,
10 TypeOpsIndirect, UserType, VTableIndirect,
11};
12
13fn type_name_arc<'a, T: Facet<'a>>(
15 _shape: &'static crate::Shape,
16 f: &mut core::fmt::Formatter<'_>,
17 opts: TypeNameOpts,
18) -> core::fmt::Result {
19 write!(f, "Arc")?;
20 if let Some(opts) = opts.for_children() {
21 write!(f, "<")?;
22 T::SHAPE.write_type_name(f, opts)?;
23 write!(f, ">")?;
24 } else {
25 write!(f, "<…>")?;
26 }
27 Ok(())
28}
29
30fn type_name_weak<'a, T: Facet<'a>>(
31 _shape: &'static crate::Shape,
32 f: &mut core::fmt::Formatter<'_>,
33 opts: TypeNameOpts,
34) -> core::fmt::Result {
35 write!(f, "Weak")?;
36 if let Some(opts) = opts.for_children() {
37 write!(f, "<")?;
38 T::SHAPE.write_type_name(f, opts)?;
39 write!(f, ">")?;
40 } else {
41 write!(f, "<…>")?;
42 }
43 Ok(())
44}
45
46unsafe fn arc_borrow<'a, T: Facet<'a>>(this: PtrConst) -> PtrConst {
48 unsafe {
49 let arc_ptr = this.as_ptr::<Arc<T>>();
50 let ptr = &**arc_ptr;
51 PtrConst::new(NonNull::from(ptr).as_ptr())
52 }
53}
54
55unsafe fn arc_new_into<'a, 'src, T: Facet<'a>>(this: PtrUninit, ptr: PtrMut) -> PtrMut {
56 unsafe {
57 let t = ptr.read::<T>();
58 let arc = Arc::new(t);
59 this.put(arc)
60 }
61}
62
63unsafe fn arc_downgrade_into<'a, 'src, T: Facet<'a>>(strong: PtrMut, weak: PtrUninit) -> PtrMut {
64 unsafe { weak.put(Arc::downgrade(strong.as_const().get::<Arc<T>>())) }
65}
66
67unsafe fn arc_str_borrow(this: PtrConst) -> PtrConst {
69 unsafe {
70 let concrete = this.get::<Arc<str>>();
71 let s: &str = concrete;
72 PtrConst::new(NonNull::from(s).as_ptr())
73 }
74}
75
76unsafe fn arc_str_downgrade_into(strong: PtrMut, weak: PtrUninit) -> PtrMut {
77 unsafe { weak.put(Arc::downgrade(strong.as_const().get::<Arc<str>>())) }
78}
79
80unsafe fn arc_slice_borrow<'a, U: Facet<'a>>(this: PtrConst) -> PtrConst {
82 unsafe {
83 let concrete = this.get::<Arc<[U]>>();
84 let s: &[U] = concrete;
85 PtrConst::new(NonNull::from(s).as_ptr())
86 }
87}
88
89unsafe fn arc_slice_downgrade_into<'a, 'src, U: Facet<'a>>(
90 strong: PtrMut,
91 weak: PtrUninit,
92) -> PtrMut {
93 unsafe { weak.put(Arc::downgrade(strong.as_const().get::<Arc<[U]>>())) }
94}
95
96fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut {
98 let v = Box::new(Vec::<U>::new());
99 let raw = Box::into_raw(v);
100 PtrMut::new(raw as *mut u8)
101}
102
103unsafe fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
104 unsafe {
105 let vec = builder.as_mut::<Vec<U>>();
106 let value = item.read::<U>();
107 vec.push(value);
108 }
109}
110
111unsafe fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut) -> PtrConst {
112 unsafe {
113 let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
114 let arc: Arc<[U]> = (*vec_box).into();
115 let arc_box = Box::new(arc);
116 PtrConst::new(NonNull::new_unchecked(Box::into_raw(arc_box)).as_ptr())
117 }
118}
119
120unsafe fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut) {
121 unsafe {
122 let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
123 }
124}
125
126unsafe fn weak_debug(
128 _this: OxPtrConst,
129 f: &mut core::fmt::Formatter<'_>,
130) -> Option<core::fmt::Result> {
131 Some(write!(f, "(Weak)"))
132}
133
134unsafe fn weak_drop<T: ?Sized>(ox: OxPtrMut) {
136 unsafe {
137 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>);
138 }
139}
140
141unsafe fn weak_clone<T: Clone>(src: OxPtrConst, dst: OxPtrMut) {
143 unsafe {
144 let value = src.get::<Weak<T>>().clone();
145 (dst.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>).write(value);
146 }
147}
148
149unsafe fn weak_default<T>(target: OxPtrMut) {
151 unsafe {
152 (target.ptr().as_ptr::<Weak<T>>() as *mut Weak<T>).write(Weak::<T>::new());
153 }
154}
155
156unsafe fn weak_upgrade_into<'a, 'src, T: Facet<'a>>(
158 weak: PtrMut,
159 strong: PtrUninit,
160) -> Option<PtrMut> {
161 unsafe { Some(strong.put(weak.as_const().get::<Weak<T>>().upgrade()?)) }
162}
163
164unsafe fn arc_drop<T>(ox: OxPtrMut) {
166 unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<Arc<T>>() as *mut Arc<T>) };
167}
168
169unsafe impl<'a, T: Facet<'a>> Facet<'a> for Arc<T> {
170 const SHAPE: &'static crate::Shape = &const {
171 ShapeBuilder::for_sized::<Self>("Arc")
172 .type_name(type_name_arc::<T>)
173 .vtable_indirect(&VTableIndirect::EMPTY)
174 .type_ops_indirect(
175 &const {
176 TypeOpsIndirect {
177 drop_in_place: arc_drop::<T>,
178 default_in_place: None,
179 clone_into: None,
180 is_truthy: None,
181 }
182 },
183 )
184 .ty(Type::User(UserType::Opaque))
185 .def(Def::Pointer(PointerDef {
186 vtable: &const {
187 PointerVTable {
188 borrow_fn: Some(arc_borrow::<T>),
189 new_into_fn: Some(arc_new_into::<T>),
190 downgrade_into_fn: Some(arc_downgrade_into::<T>),
191 ..PointerVTable::new()
192 }
193 },
194 pointee: Some(T::SHAPE),
195 weak: Some(|| <Weak<T> as Facet>::SHAPE),
196 strong: None,
197 flags: PointerFlags::ATOMIC,
198 known: Some(KnownPointer::Arc),
199 }))
200 .type_params(&[crate::TypeParam {
201 name: "T",
202 shape: T::SHAPE,
203 }])
204 .inner(T::SHAPE)
205 .build()
206 };
207}
208
209unsafe fn arc_str_drop(ox: OxPtrMut) {
211 unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<Arc<str>>() as *mut Arc<str>) };
212}
213
214unsafe fn weak_str_drop(ox: OxPtrMut) {
216 unsafe {
217 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<str>>() as *mut Weak<str>);
218 }
219}
220
221static ARC_STR_TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
223 drop_in_place: arc_str_drop,
224 default_in_place: None,
225 clone_into: None,
226 is_truthy: None,
227};
228
229unsafe impl<'a> Facet<'a> for Arc<str> {
230 const SHAPE: &'static crate::Shape = &const {
231 fn type_name_arc_str(
232 _shape: &'static crate::Shape,
233 f: &mut core::fmt::Formatter<'_>,
234 opts: TypeNameOpts,
235 ) -> core::fmt::Result {
236 write!(f, "Arc")?;
237 if let Some(opts) = opts.for_children() {
238 write!(f, "<")?;
239 str::SHAPE.write_type_name(f, opts)?;
240 write!(f, ">")?;
241 } else {
242 write!(f, "<…>")?;
243 }
244 Ok(())
245 }
246
247 ShapeBuilder::for_sized::<Self>("Arc")
248 .type_name(type_name_arc_str)
249 .vtable_indirect(&const { VTableIndirect::EMPTY })
250 .type_ops_indirect(&ARC_STR_TYPE_OPS)
251 .ty(Type::User(UserType::Opaque))
252 .def(Def::Pointer(PointerDef {
253 vtable: &const {
254 PointerVTable {
255 borrow_fn: Some(arc_str_borrow),
256 downgrade_into_fn: Some(arc_str_downgrade_into),
257 ..PointerVTable::new()
258 }
259 },
260 pointee: Some(str::SHAPE),
261 weak: Some(|| <Weak<str> as Facet>::SHAPE),
262 strong: None,
263 flags: PointerFlags::ATOMIC,
264 known: Some(KnownPointer::Arc),
265 }))
266 .type_params(&[crate::TypeParam {
267 name: "T",
268 shape: str::SHAPE,
269 }])
270 .inner(str::SHAPE)
271 .build()
272 };
273}
274
275unsafe fn arc_slice_drop<U>(ox: OxPtrMut) {
277 unsafe { core::ptr::drop_in_place(ox.ptr().as_ptr::<Arc<[U]>>() as *mut Arc<[U]>) };
278}
279
280unsafe fn weak_slice_drop<U>(ox: OxPtrMut) {
282 unsafe {
283 core::ptr::drop_in_place(ox.ptr().as_ptr::<Weak<[U]>>() as *mut Weak<[U]>);
284 }
285}
286
287unsafe impl<'a, U: Facet<'a>> Facet<'a> for Arc<[U]> {
288 const SHAPE: &'static crate::Shape = &const {
289 fn type_name_arc_slice<'a, U: Facet<'a>>(
290 _shape: &'static crate::Shape,
291 f: &mut core::fmt::Formatter<'_>,
292 opts: TypeNameOpts,
293 ) -> core::fmt::Result {
294 write!(f, "Arc")?;
295 if let Some(opts) = opts.for_children() {
296 write!(f, "<")?;
297 <[U]>::SHAPE.write_type_name(f, opts)?;
298 write!(f, ">")?;
299 } else {
300 write!(f, "<…>")?;
301 }
302 Ok(())
303 }
304
305 ShapeBuilder::for_sized::<Self>("Arc")
306 .type_name(type_name_arc_slice::<U>)
307 .vtable_indirect(&VTableIndirect::EMPTY)
308 .type_ops_indirect(
309 &const {
310 TypeOpsIndirect {
311 drop_in_place: arc_slice_drop::<U>,
312 default_in_place: None,
313 clone_into: None,
314 is_truthy: None,
315 }
316 },
317 )
318 .ty(Type::User(UserType::Opaque))
319 .def(Def::Pointer(PointerDef {
320 vtable: &const {
321 PointerVTable {
322 borrow_fn: Some(arc_slice_borrow::<U>),
323 downgrade_into_fn: Some(arc_slice_downgrade_into::<U>),
324 slice_builder_vtable: Some(
325 &const {
326 SliceBuilderVTable::new(
327 slice_builder_new::<U>,
328 slice_builder_push::<U>,
329 slice_builder_convert::<U>,
330 slice_builder_free::<U>,
331 )
332 },
333 ),
334 ..PointerVTable::new()
335 }
336 },
337 pointee: Some(<[U]>::SHAPE),
338 weak: Some(|| <Weak<[U]> as Facet>::SHAPE),
339 strong: None,
340 flags: PointerFlags::ATOMIC,
341 known: Some(KnownPointer::Arc),
342 }))
343 .type_params(&[crate::TypeParam {
344 name: "T",
345 shape: <[U]>::SHAPE,
346 }])
347 .inner(<[U]>::SHAPE)
348 .build()
349 };
350}
351
352unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
353 const SHAPE: &'static crate::Shape = &const {
354 const VTABLE: VTableIndirect = VTableIndirect {
355 display: None,
356 debug: Some(weak_debug),
357 hash: None,
358 invariants: None,
359 parse: None,
360 try_from: None,
361 try_into_inner: None,
362 try_borrow_inner: None,
363 partial_eq: None,
364 partial_cmp: None,
365 cmp: None,
366 };
367
368 ShapeBuilder::for_sized::<Self>("Weak")
369 .type_name(type_name_weak::<T>)
370 .vtable_indirect(&VTABLE)
371 .type_ops_indirect(
372 &const {
373 TypeOpsIndirect {
374 drop_in_place: weak_drop::<T>,
375 default_in_place: Some(weak_default::<T>),
376 clone_into: Some(weak_clone::<Weak<T>>),
377 is_truthy: None,
378 }
379 },
380 )
381 .ty(Type::User(UserType::Opaque))
382 .def(Def::Pointer(PointerDef {
383 vtable: &const {
384 PointerVTable {
385 upgrade_into_fn: Some(weak_upgrade_into::<T>),
386 ..PointerVTable::new()
387 }
388 },
389 pointee: Some(T::SHAPE),
390 weak: None,
391 strong: Some(<Arc<T> as Facet>::SHAPE),
392 flags: PointerFlags::ATOMIC.union(PointerFlags::WEAK),
393 known: Some(KnownPointer::ArcWeak),
394 }))
395 .type_params(&[crate::TypeParam {
396 name: "T",
397 shape: T::SHAPE,
398 }])
399 .inner(T::SHAPE)
400 .build()
401 };
402}
403
404static WEAK_STR_TYPE_OPS: TypeOpsIndirect = TypeOpsIndirect {
406 drop_in_place: weak_str_drop,
407 default_in_place: None,
408 clone_into: Some(weak_clone::<Weak<str>>),
409 is_truthy: None,
410};
411
412static WEAK_VTABLE: VTableIndirect = VTableIndirect {
413 display: None,
414 debug: Some(weak_debug),
415 hash: None,
416 invariants: None,
417 parse: None,
418 try_from: None,
419 try_into_inner: None,
420 try_borrow_inner: None,
421 partial_eq: None,
422 partial_cmp: None,
423 cmp: None,
424};
425
426unsafe impl<'a> Facet<'a> for Weak<str> {
427 const SHAPE: &'static crate::Shape = &const {
428 fn type_name_weak_str(
429 _shape: &'static crate::Shape,
430 f: &mut core::fmt::Formatter<'_>,
431 opts: TypeNameOpts,
432 ) -> core::fmt::Result {
433 write!(f, "Weak")?;
434 if let Some(opts) = opts.for_children() {
435 write!(f, "<")?;
436 str::SHAPE.write_type_name(f, opts)?;
437 write!(f, ">")?;
438 } else {
439 write!(f, "<…>")?;
440 }
441 Ok(())
442 }
443
444 ShapeBuilder::for_sized::<Self>("Weak")
445 .type_name(type_name_weak_str)
446 .vtable_indirect(&WEAK_VTABLE)
447 .type_ops_indirect(&WEAK_STR_TYPE_OPS)
448 .ty(Type::User(UserType::Opaque))
449 .def(Def::Pointer(PointerDef {
450 vtable: &const {
451 PointerVTable {
452 upgrade_into_fn: Some(|weak, strong| unsafe {
453 let upgraded = weak.as_const().get::<Weak<str>>().upgrade()?;
454 Some(strong.put(upgraded))
455 }),
456 ..PointerVTable::new()
457 }
458 },
459 pointee: Some(str::SHAPE),
460 weak: None,
461 strong: Some(<Arc<str> as Facet>::SHAPE),
462 flags: PointerFlags::ATOMIC.union(PointerFlags::WEAK),
463 known: Some(KnownPointer::ArcWeak),
464 }))
465 .type_params(&[crate::TypeParam {
466 name: "T",
467 shape: str::SHAPE,
468 }])
469 .inner(str::SHAPE)
470 .build()
471 };
472}
473
474unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
475 const SHAPE: &'static crate::Shape = &const {
476 fn type_name_weak_slice<'a, U: Facet<'a>>(
477 _shape: &'static crate::Shape,
478 f: &mut core::fmt::Formatter<'_>,
479 opts: TypeNameOpts,
480 ) -> core::fmt::Result {
481 write!(f, "Weak")?;
482 if let Some(opts) = opts.for_children() {
483 write!(f, "<")?;
484 <[U]>::SHAPE.write_type_name(f, opts)?;
485 write!(f, ">")?;
486 } else {
487 write!(f, "<…>")?;
488 }
489 Ok(())
490 }
491
492 const VTABLE: VTableIndirect = VTableIndirect {
493 display: None,
494 debug: Some(weak_debug),
495 hash: None,
496 invariants: None,
497 parse: None,
498 try_from: None,
499 try_into_inner: None,
500 try_borrow_inner: None,
501 partial_eq: None,
502 partial_cmp: None,
503 cmp: None,
504 };
505
506 ShapeBuilder::for_sized::<Self>("Weak")
507 .type_name(type_name_weak_slice::<U>)
508 .vtable_indirect(&VTABLE)
509 .type_ops_indirect(
510 &const {
511 TypeOpsIndirect {
512 drop_in_place: weak_slice_drop::<U>,
513 default_in_place: None,
514 clone_into: Some(weak_clone::<Weak<[U]>>),
515 is_truthy: None,
516 }
517 },
518 )
519 .ty(Type::User(UserType::Opaque))
520 .def(Def::Pointer(PointerDef {
521 vtable: &const {
522 PointerVTable {
523 upgrade_into_fn: Some(|weak, strong| unsafe {
524 let upgraded = weak.as_const().get::<Weak<[U]>>().upgrade()?;
525 Some(strong.put(upgraded))
526 }),
527 ..PointerVTable::new()
528 }
529 },
530 pointee: Some(<[U]>::SHAPE),
531 weak: None,
532 strong: Some(<Arc<[U]> as Facet>::SHAPE),
533 flags: PointerFlags::ATOMIC.union(PointerFlags::WEAK),
534 known: Some(KnownPointer::ArcWeak),
535 }))
536 .type_params(&[crate::TypeParam {
537 name: "T",
538 shape: <[U]>::SHAPE,
539 }])
540 .inner(<[U]>::SHAPE)
541 .build()
542 };
543}
544
545#[cfg(test)]
546mod tests {
547 use core::mem::ManuallyDrop;
548
549 use alloc::string::String;
550 use alloc::sync::{Arc, Weak as ArcWeak};
551
552 use super::*;
553
554 #[test]
555 fn test_arc_type_params() {
556 let [type_param_1] = <Arc<i32>>::SHAPE.type_params else {
557 panic!("Arc<T> should only have 1 type param")
558 };
559 assert_eq!(type_param_1.shape(), i32::SHAPE);
560 }
561
562 #[test]
563 fn test_arc_vtable_1_new_borrow_drop() {
564 facet_testhelpers::setup();
565
566 let arc_shape = <Arc<String>>::SHAPE;
567 let arc_def = arc_shape
568 .def
569 .into_pointer()
570 .expect("Arc<T> should have a smart pointer definition");
571
572 let arc_uninit_ptr = arc_shape.allocate().unwrap();
574
575 let new_into_fn = arc_def
577 .vtable
578 .new_into_fn
579 .expect("Arc<T> should have new_into_fn");
580
581 let mut value = ManuallyDrop::new(String::from("example"));
583 let arc_ptr = unsafe {
584 new_into_fn(
585 arc_uninit_ptr,
586 PtrMut::new(NonNull::from(&mut value).as_ptr()),
587 )
588 };
589 let borrow_fn = arc_def
593 .vtable
594 .borrow_fn
595 .expect("Arc<T> should have borrow_fn");
596
597 let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
599 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
601
602 unsafe {
605 arc_shape
606 .call_drop_in_place(arc_ptr)
607 .expect("Arc<T> should have drop_in_place");
608 }
609
610 unsafe { arc_shape.deallocate_mut(arc_ptr).unwrap() };
613 }
614
615 #[test]
616 fn test_arc_vtable_2_downgrade_upgrade_drop() {
617 facet_testhelpers::setup();
618
619 let arc_shape = <Arc<String>>::SHAPE;
620 let arc_def = arc_shape
621 .def
622 .into_pointer()
623 .expect("Arc<T> should have a smart pointer definition");
624
625 let weak_shape = <ArcWeak<String>>::SHAPE;
626 let weak_def = weak_shape
627 .def
628 .into_pointer()
629 .expect("ArcWeak<T> should have a smart pointer definition");
630
631 let arc1_uninit_ptr = arc_shape.allocate().unwrap();
633 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
634 let mut value = ManuallyDrop::new(String::from("example"));
635 let arc1_ptr = unsafe {
636 new_into_fn(
637 arc1_uninit_ptr,
638 PtrMut::new(NonNull::from(&mut value).as_ptr()),
639 )
640 };
641
642 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
644 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
645 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
647
648 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
650 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
651 let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
654 .expect("Upgrade should succeed while original Arc exists");
655
656 let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
658 let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
660 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
662
663 unsafe {
665 arc_shape.call_drop_in_place(arc1_ptr).unwrap();
667 arc_shape.deallocate_mut(arc1_ptr).unwrap();
668 arc_shape.call_drop_in_place(arc2_ptr).unwrap();
669 arc_shape.deallocate_mut(arc2_ptr).unwrap();
670
671 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
673 weak_shape.deallocate_mut(weak1_ptr).unwrap();
674 }
675 }
676
677 #[test]
678 fn test_arc_vtable_3_downgrade_drop_try_upgrade() {
679 facet_testhelpers::setup();
680
681 let arc_shape = <Arc<String>>::SHAPE;
682 let arc_def = arc_shape
683 .def
684 .into_pointer()
685 .expect("Arc<T> should have a smart pointer definition");
686
687 let weak_shape = <ArcWeak<String>>::SHAPE;
688 let weak_def = weak_shape
689 .def
690 .into_pointer()
691 .expect("ArcWeak<T> should have a smart pointer definition");
692
693 let arc1_uninit_ptr = arc_shape.allocate().unwrap();
695 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
696 let mut value = ManuallyDrop::new(String::from("example"));
697 let arc1_ptr = unsafe {
698 new_into_fn(
699 arc1_uninit_ptr,
700 PtrMut::new(NonNull::from(&mut value).as_ptr()),
701 )
702 };
703
704 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
706 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
707 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
709
710 unsafe {
712 arc_shape.call_drop_in_place(arc1_ptr).unwrap();
713 arc_shape.deallocate_mut(arc1_ptr).unwrap();
714 }
715
716 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
718 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
719 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
721
722 assert!(
724 upgrade_result.is_none(),
725 "Upgrade should fail after the strong Arc is dropped"
726 );
727
728 unsafe {
730 arc_shape.deallocate_uninit(arc2_uninit_ptr).unwrap();
732
733 weak_shape.call_drop_in_place(weak1_ptr).unwrap();
735 weak_shape.deallocate_mut(weak1_ptr).unwrap();
736 }
737 }
738
739 #[test]
740 fn test_arc_vtable_6_slice_builder() {
741 facet_testhelpers::setup();
742
743 let arc_slice_shape = <Arc<[i32]>>::SHAPE;
745 let arc_slice_def = arc_slice_shape
746 .def
747 .into_pointer()
748 .expect("Arc<[i32]> should have a smart pointer definition");
749
750 let slice_builder_vtable = arc_slice_def
752 .vtable
753 .slice_builder_vtable
754 .expect("Arc<[i32]> should have slice_builder_vtable");
755
756 let builder_ptr = (slice_builder_vtable.new_fn)();
758
759 let push_fn = slice_builder_vtable.push_fn;
761 let values = [1i32, 2, 3, 4, 5];
762 for &value in &values {
763 let mut value_copy = value;
764 let value_ptr = PtrMut::new(NonNull::from(&mut value_copy).as_ptr());
765 unsafe { push_fn(builder_ptr, value_ptr) };
766 }
767
768 let convert_fn = slice_builder_vtable.convert_fn;
770 let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
771
772 let borrow_fn = arc_slice_def
774 .vtable
775 .borrow_fn
776 .expect("Arc<[i32]> should have borrow_fn");
777 let borrowed_ptr = unsafe { borrow_fn(arc_slice_ptr) };
778
779 let slice = unsafe { borrowed_ptr.get::<[i32]>() };
781 assert_eq!(slice, &[1, 2, 3, 4, 5]);
782
783 unsafe {
785 let _ = Box::from_raw(arc_slice_ptr.as_ptr::<Arc<[i32]>>() as *mut Arc<[i32]>);
786 }
787 }
788
789 #[test]
790 fn test_arc_vtable_7_slice_builder_free() {
791 facet_testhelpers::setup();
792
793 let arc_slice_shape = <Arc<[String]>>::SHAPE;
795 let arc_slice_def = arc_slice_shape
796 .def
797 .into_pointer()
798 .expect("Arc<[String]> should have a smart pointer definition");
799
800 let slice_builder_vtable = arc_slice_def
802 .vtable
803 .slice_builder_vtable
804 .expect("Arc<[String]> should have slice_builder_vtable");
805
806 let builder_ptr = (slice_builder_vtable.new_fn)();
808
809 let push_fn = slice_builder_vtable.push_fn;
811 let strings = ["hello", "world", "test"];
812 for &s in &strings {
813 let mut value = ManuallyDrop::new(String::from(s));
814 let value_ptr = PtrMut::new(NonNull::from(&mut value).as_ptr());
815 unsafe { push_fn(builder_ptr, value_ptr) };
816 }
817
818 let free_fn = slice_builder_vtable.free_fn;
821 unsafe { free_fn(builder_ptr) };
822
823 }
825}