1use alloc::boxed::Box;
2use alloc::sync::{Arc, Weak};
3use alloc::vec::Vec;
4
5use crate::{
6 Def, Facet, KnownPointer, PointerDef, PointerFlags, PointerVTable, PtrConst, PtrConstWide,
7 PtrMut, PtrUninit, Shape, SliceBuilderVTable, TryBorrowInnerError, TryFromError,
8 TryIntoInnerError, Type, UserType, ValueVTable, value_vtable,
9};
10
11unsafe impl<'a, T: Facet<'a>> Facet<'a> for Arc<T> {
12 const VTABLE: &'static ValueVTable = &const {
13 unsafe fn try_from<'a, 'src, 'dst, T: Facet<'a>>(
15 src_ptr: PtrConst<'src>,
16 src_shape: &'static Shape,
17 dst: PtrUninit<'dst>,
18 ) -> Result<PtrMut<'dst>, TryFromError> {
19 if src_shape.id != T::SHAPE.id {
20 return Err(TryFromError::UnsupportedSourceShape {
21 src_shape,
22 expected: &[T::SHAPE],
23 });
24 }
25 let t = unsafe { src_ptr.read::<T>() };
26 let arc = Arc::new(t);
27 Ok(unsafe { dst.put(arc) })
28 }
29
30 unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
31 src_ptr: PtrMut<'src>,
32 dst: PtrUninit<'dst>,
33 ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
34 use alloc::sync::Arc;
35
36 let arc = unsafe { src_ptr.read::<Arc<T>>() };
38
39 match Arc::try_unwrap(arc) {
41 Ok(inner) => Ok(unsafe { dst.put(inner) }),
42 Err(arc) => {
43 core::mem::forget(arc);
45 Err(TryIntoInnerError::Unavailable)
46 }
47 }
48 }
49
50 unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
51 src_ptr: PtrConst<'src>,
52 ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
53 let arc = unsafe { src_ptr.get::<Arc<T>>() };
54 Ok(PtrConst::new(&**arc))
55 }
56
57 let mut vtable = value_vtable!(alloc::sync::Arc<T>, |f, opts| {
58 write!(f, "{}", Self::SHAPE.type_identifier)?;
59 if let Some(opts) = opts.for_children() {
60 write!(f, "<")?;
61 (T::SHAPE.vtable.type_name())(f, opts)?;
62 write!(f, ">")?;
63 } else {
64 write!(f, "<…>")?;
65 }
66 Ok(())
67 });
68
69 {
70 let vtable = vtable.sized_mut().unwrap();
71 vtable.try_from = || Some(try_from::<T>);
72 vtable.try_into_inner = || Some(try_into_inner::<T>);
73 vtable.try_borrow_inner = || Some(try_borrow_inner::<T>);
74 }
75 vtable
76 };
77
78 const SHAPE: &'static crate::Shape = &const {
79 fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
81 T::SHAPE
82 }
83
84 crate::Shape::builder_for_sized::<Self>()
85 .type_identifier("Arc")
86 .type_params(&[crate::TypeParam {
87 name: "T",
88 shape: || T::SHAPE,
89 }])
90 .ty(Type::User(UserType::Opaque))
91 .def(Def::Pointer(
92 PointerDef::builder()
93 .pointee(|| T::SHAPE)
94 .flags(PointerFlags::ATOMIC)
95 .known(KnownPointer::Arc)
96 .weak(|| <Weak<T> as Facet>::SHAPE)
97 .vtable(
98 &const {
99 PointerVTable::builder()
100 .borrow_fn(|this| {
101 let arc_ptr = unsafe { this.as_ptr::<Arc<T>>() };
102 let ptr = unsafe { Arc::as_ptr(&*arc_ptr) };
103 PtrConst::new(ptr).into()
104 })
105 .new_into_fn(|this, ptr| {
106 let t = unsafe { ptr.read::<T>() };
107 let arc = Arc::new(t);
108 unsafe { this.put(arc) }
109 })
110 .downgrade_into_fn(|strong, weak| unsafe {
111 weak.put(Arc::downgrade(strong.get::<Self>()))
112 })
113 .build()
114 },
115 )
116 .build(),
117 ))
118 .inner(inner_shape::<T>)
119 .build()
120 };
121}
122
123unsafe impl<'a> Facet<'a> for Arc<str> {
124 const VTABLE: &'static ValueVTable = &const {
125 value_vtable!(alloc::sync::Arc<str>, |f, opts| {
126 write!(f, "{}", Self::SHAPE.type_identifier)?;
127 if let Some(opts) = opts.for_children() {
128 write!(f, "<")?;
129 (str::SHAPE.vtable.type_name())(f, opts)?;
130 write!(f, ">")?;
131 } else {
132 write!(f, "<…>")?;
133 }
134 Ok(())
135 })
136 };
137
138 const SHAPE: &'static crate::Shape = &const {
139 fn inner_shape() -> &'static Shape {
141 str::SHAPE
142 }
143
144 crate::Shape::builder_for_sized::<Self>()
145 .type_identifier("Arc")
146 .type_params(&[crate::TypeParam {
147 name: "T",
148 shape: || str::SHAPE,
149 }])
150 .ty(Type::User(UserType::Opaque))
151 .def(Def::Pointer(
152 PointerDef::builder()
153 .pointee(|| str::SHAPE)
154 .flags(PointerFlags::ATOMIC)
155 .known(KnownPointer::Arc)
156 .weak(|| <Weak<str> as Facet>::SHAPE)
157 .vtable(
158 &const {
159 PointerVTable::builder()
160 .borrow_fn(|this| unsafe {
161 let concrete = this.get::<Arc<str>>();
162 let s: &str = concrete;
163 PtrConstWide::new(&raw const *s).into()
164 })
165 .new_into_fn(|_this, _ptr| todo!())
166 .downgrade_into_fn(|_strong, _weak| todo!())
167 .build()
168 },
169 )
170 .build(),
171 ))
172 .inner(inner_shape)
173 .build()
174 };
175}
176
177unsafe impl<'a, U: Facet<'a>> Facet<'a> for Arc<[U]> {
178 const VTABLE: &'static ValueVTable = &const {
179 value_vtable!(alloc::sync::Arc<[U]>, |f, opts| {
180 write!(f, "{}", Self::SHAPE.type_identifier)?;
181 if let Some(opts) = opts.for_children() {
182 write!(f, "<")?;
183 (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
184 write!(f, ">")?;
185 } else {
186 write!(f, "<…>")?;
187 }
188 Ok(())
189 })
190 };
191
192 const SHAPE: &'static crate::Shape = &const {
193 fn inner_shape<'a, U: Facet<'a>>() -> &'static Shape {
195 <[U]>::SHAPE
196 }
197
198 fn slice_builder_new<'a, U: Facet<'a>>() -> PtrMut<'static> {
199 let v = Box::new(Vec::<U>::new());
200 let raw = Box::into_raw(v);
201 PtrMut::new(raw)
202 }
203
204 fn slice_builder_push<'a, U: Facet<'a>>(builder: PtrMut, item: PtrMut) {
205 unsafe {
206 let vec = builder.as_mut::<Vec<U>>();
207 let value = item.read::<U>();
208 vec.push(value);
209 }
210 }
211
212 fn slice_builder_convert<'a, U: Facet<'a>>(builder: PtrMut<'static>) -> PtrConst<'static> {
213 unsafe {
214 let vec_box = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
215 let arc: Arc<[U]> = (*vec_box).into();
216 let arc_box = Box::new(arc);
217 PtrConst::new(Box::into_raw(arc_box) as *const Arc<[U]>)
218 }
219 }
220
221 fn slice_builder_free<'a, U: Facet<'a>>(builder: PtrMut<'static>) {
222 unsafe {
223 let _ = Box::from_raw(builder.as_ptr::<Vec<U>>() as *mut Vec<U>);
224 }
225 }
226
227 crate::Shape::builder_for_sized::<Self>()
228 .type_identifier("Arc")
229 .type_params(&[crate::TypeParam {
230 name: "T",
231 shape: || <[U]>::SHAPE,
232 }])
233 .ty(Type::User(UserType::Opaque))
234 .def(Def::Pointer(
235 PointerDef::builder()
236 .pointee(|| <[U]>::SHAPE)
237 .flags(PointerFlags::ATOMIC)
238 .known(KnownPointer::Arc)
239 .weak(|| <Weak<[U]> as Facet>::SHAPE)
240 .vtable(
241 &const {
242 PointerVTable::builder()
243 .borrow_fn(|this| unsafe {
244 let concrete = this.get::<Arc<[U]>>();
245 let s: &[U] = concrete;
246 PtrConstWide::new(&raw const *s).into()
247 })
248 .new_into_fn(|_this, _ptr| todo!())
249 .downgrade_into_fn(|_strong, _weak| todo!())
250 .slice_builder_vtable(
251 &const {
252 SliceBuilderVTable::builder()
253 .new_fn(slice_builder_new::<U>)
254 .push_fn(slice_builder_push::<U>)
255 .convert_fn(slice_builder_convert::<U>)
256 .free_fn(slice_builder_free::<U>)
257 .build()
258 },
259 )
260 .build()
261 },
262 )
263 .build(),
264 ))
265 .inner(inner_shape::<U>)
266 .build()
267 };
268}
269
270unsafe impl<'a, T: Facet<'a>> Facet<'a> for Weak<T> {
271 const VTABLE: &'static ValueVTable = &const {
272 value_vtable!(alloc::sync::Weak<T>, |f, opts| {
273 write!(f, "{}", Self::SHAPE.type_identifier)?;
274 if let Some(opts) = opts.for_children() {
275 write!(f, "<")?;
276 (T::SHAPE.vtable.type_name())(f, opts)?;
277 write!(f, ">")?;
278 } else {
279 write!(f, "<…>")?;
280 }
281 Ok(())
282 })
283 };
284
285 const SHAPE: &'static crate::Shape = &const {
286 fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape {
288 T::SHAPE
289 }
290
291 crate::Shape::builder_for_sized::<Self>()
292 .type_identifier("Weak")
293 .type_params(&[crate::TypeParam {
294 name: "T",
295 shape: || T::SHAPE,
296 }])
297 .ty(Type::User(UserType::Opaque))
298 .def(Def::Pointer(
299 PointerDef::builder()
300 .pointee(|| T::SHAPE)
301 .flags(PointerFlags::ATOMIC.union(PointerFlags::WEAK))
302 .known(KnownPointer::ArcWeak)
303 .strong(|| <Arc<T> as Facet>::SHAPE)
304 .vtable(
305 &const {
306 PointerVTable::builder()
307 .upgrade_into_fn(|weak, strong| unsafe {
308 Some(strong.put(weak.get::<Self>().upgrade()?))
309 })
310 .build()
311 },
312 )
313 .build(),
314 ))
315 .inner(inner_shape::<T>)
316 .build()
317 };
318}
319
320unsafe impl<'a> Facet<'a> for Weak<str> {
321 const VTABLE: &'static ValueVTable = &const {
322 value_vtable!(alloc::sync::Weak<str>, |f, opts| {
323 write!(f, "{}", Self::SHAPE.type_identifier)?;
324 if let Some(opts) = opts.for_children() {
325 write!(f, "<")?;
326 (str::SHAPE.vtable.type_name())(f, opts)?;
327 write!(f, ">")?;
328 } else {
329 write!(f, "<…>")?;
330 }
331 Ok(())
332 })
333 };
334
335 const SHAPE: &'static crate::Shape = &const {
336 fn inner_shape() -> &'static Shape {
338 str::SHAPE
339 }
340
341 crate::Shape::builder_for_sized::<Self>()
342 .type_identifier("Weak")
343 .type_params(&[crate::TypeParam {
344 name: "T",
345 shape: || str::SHAPE,
346 }])
347 .ty(Type::User(UserType::Opaque))
348 .def(Def::Pointer(
349 PointerDef::builder()
350 .pointee(|| str::SHAPE)
351 .flags(PointerFlags::ATOMIC.union(PointerFlags::WEAK))
352 .known(KnownPointer::ArcWeak)
353 .strong(|| <Arc<str> as Facet>::SHAPE)
354 .vtable(
355 &const {
356 PointerVTable::builder()
357 .upgrade_into_fn(|_weak, _strong| todo!())
358 .build()
359 },
360 )
361 .build(),
362 ))
363 .inner(inner_shape)
364 .build()
365 };
366}
367
368unsafe impl<'a, U: Facet<'a>> Facet<'a> for Weak<[U]> {
369 const VTABLE: &'static ValueVTable = &const {
370 value_vtable!(alloc::sync::Weak<[U]>, |f, opts| {
371 write!(f, "{}", Self::SHAPE.type_identifier)?;
372 if let Some(opts) = opts.for_children() {
373 write!(f, "<")?;
374 (<[U]>::SHAPE.vtable.type_name())(f, opts)?;
375 write!(f, ">")?;
376 } else {
377 write!(f, "<…>")?;
378 }
379 Ok(())
380 })
381 };
382
383 const SHAPE: &'static crate::Shape = &const {
384 fn inner_shape<'a, U: Facet<'a>>() -> &'static Shape {
385 <[U]>::SHAPE
386 }
387
388 crate::Shape::builder_for_sized::<Self>()
389 .type_identifier("Weak")
390 .type_params(&[crate::TypeParam {
391 name: "T",
392 shape: || <[U]>::SHAPE,
393 }])
394 .ty(Type::User(UserType::Opaque))
395 .def(Def::Pointer(
396 PointerDef::builder()
397 .pointee(|| <[U]>::SHAPE)
398 .flags(PointerFlags::ATOMIC.union(PointerFlags::WEAK))
399 .known(KnownPointer::ArcWeak)
400 .strong(|| <Arc<[U]> as Facet>::SHAPE)
401 .vtable(
402 &const {
403 PointerVTable::builder()
404 .upgrade_into_fn(|weak, strong| unsafe {
405 Some(strong.put(weak.get::<Self>().upgrade()?))
406 })
407 .build()
408 },
409 )
410 .build(),
411 ))
412 .inner(inner_shape::<U>)
413 .build()
414 };
415}
416
417#[cfg(test)]
418mod tests {
419 use alloc::string::String;
420 use alloc::sync::{Arc, Weak as ArcWeak};
421
422 use super::*;
423
424 #[test]
425 fn test_arc_type_params() {
426 let [type_param_1] = <Arc<i32>>::SHAPE.type_params else {
427 panic!("Arc<T> should only have 1 type param")
428 };
429 assert_eq!(type_param_1.shape(), i32::SHAPE);
430 }
431
432 #[test]
433 fn test_arc_vtable_1_new_borrow_drop() {
434 facet_testhelpers::setup();
435
436 let arc_shape = <Arc<String>>::SHAPE;
437 let arc_def = arc_shape
438 .def
439 .into_pointer()
440 .expect("Arc<T> should have a smart pointer definition");
441
442 let arc_uninit_ptr = arc_shape.allocate().unwrap();
444
445 let new_into_fn = arc_def
447 .vtable
448 .new_into_fn
449 .expect("Arc<T> should have new_into_fn");
450
451 let mut value = String::from("example");
453 let arc_ptr = unsafe { new_into_fn(arc_uninit_ptr, PtrMut::new(&raw mut value)) };
454 core::mem::forget(value);
456
457 let borrow_fn = arc_def
459 .vtable
460 .borrow_fn
461 .expect("Arc<T> should have borrow_fn");
462
463 let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
465 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
467
468 let drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)()
470 .expect("Arc<T> should have drop_in_place");
471
472 unsafe { drop_fn(arc_ptr) };
475
476 unsafe { arc_shape.deallocate_mut(arc_ptr).unwrap() };
479 }
480
481 #[test]
482 fn test_arc_vtable_2_downgrade_upgrade_drop() {
483 facet_testhelpers::setup();
484
485 let arc_shape = <Arc<String>>::SHAPE;
486 let arc_def = arc_shape
487 .def
488 .into_pointer()
489 .expect("Arc<T> should have a smart pointer definition");
490
491 let weak_shape = <ArcWeak<String>>::SHAPE;
492 let weak_def = weak_shape
493 .def
494 .into_pointer()
495 .expect("ArcWeak<T> should have a smart pointer definition");
496
497 let arc1_uninit_ptr = arc_shape.allocate().unwrap();
499 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
500 let mut value = String::from("example");
501 let arc1_ptr = unsafe { new_into_fn(arc1_uninit_ptr, PtrMut::new(&raw mut value)) };
502 core::mem::forget(value); let weak1_uninit_ptr = weak_shape.allocate().unwrap();
506 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
507 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
509
510 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
512 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
513 let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
516 .expect("Upgrade should succeed while original Arc exists");
517
518 let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
520 let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
522 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
524
525 let arc_drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
527 let weak_drop_fn = (weak_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
528
529 unsafe {
530 arc_drop_fn(arc1_ptr);
532 arc_shape.deallocate_mut(arc1_ptr).unwrap();
533 arc_drop_fn(arc2_ptr);
534 arc_shape.deallocate_mut(arc2_ptr).unwrap();
535
536 weak_drop_fn(weak1_ptr);
538 weak_shape.deallocate_mut(weak1_ptr).unwrap();
539 }
540 }
541
542 #[test]
543 fn test_arc_vtable_3_downgrade_drop_try_upgrade() {
544 facet_testhelpers::setup();
545
546 let arc_shape = <Arc<String>>::SHAPE;
547 let arc_def = arc_shape
548 .def
549 .into_pointer()
550 .expect("Arc<T> should have a smart pointer definition");
551
552 let weak_shape = <ArcWeak<String>>::SHAPE;
553 let weak_def = weak_shape
554 .def
555 .into_pointer()
556 .expect("ArcWeak<T> should have a smart pointer definition");
557
558 let arc1_uninit_ptr = arc_shape.allocate().unwrap();
560 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
561 let mut value = String::from("example");
562 let arc1_ptr = unsafe { new_into_fn(arc1_uninit_ptr, PtrMut::new(&raw mut value)) };
563 core::mem::forget(value);
564
565 let weak1_uninit_ptr = weak_shape.allocate().unwrap();
567 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
568 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
570
571 let arc_drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
573 unsafe {
574 arc_drop_fn(arc1_ptr);
575 arc_shape.deallocate_mut(arc1_ptr).unwrap();
576 }
577
578 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
580 let arc2_uninit_ptr = arc_shape.allocate().unwrap();
581 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
583
584 assert!(
586 upgrade_result.is_none(),
587 "Upgrade should fail after the strong Arc is dropped"
588 );
589
590 let weak_drop_fn = (weak_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
592 unsafe {
593 arc_shape.deallocate_uninit(arc2_uninit_ptr).unwrap();
595
596 weak_drop_fn(weak1_ptr);
598 weak_shape.deallocate_mut(weak1_ptr).unwrap();
599 }
600 }
601
602 #[test]
603 fn test_arc_vtable_4_try_from() {
604 facet_testhelpers::setup();
605
606 let string_shape = <String>::SHAPE;
608 let arc_shape = <Arc<String>>::SHAPE;
609 let arc_def = arc_shape
610 .def
611 .into_pointer()
612 .expect("Arc<T> should have a smart pointer definition");
613
614 let value = String::from("try_from test");
616 let value_ptr = PtrConst::new(&value as *const String as *const u8);
617
618 let arc_uninit_ptr = arc_shape.allocate().unwrap();
620
621 let try_from_fn =
623 (arc_shape.vtable.sized().unwrap().try_from)().expect("Arc<T> should have try_from");
624
625 let arc_ptr = unsafe { try_from_fn(value_ptr, string_shape, arc_uninit_ptr) }
627 .expect("try_from should succeed");
628 core::mem::forget(value);
629
630 let borrow_fn = arc_def
632 .vtable
633 .borrow_fn
634 .expect("Arc<T> should have borrow_fn");
635 let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
636
637 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "try_from test");
639
640 let drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)()
642 .expect("Arc<T> should have drop_in_place");
643
644 unsafe {
645 drop_fn(arc_ptr);
646 arc_shape.deallocate_mut(arc_ptr).unwrap();
647 }
648 }
649
650 #[test]
651 fn test_arc_vtable_5_try_into_inner() {
652 facet_testhelpers::setup();
653
654 let string_shape = <String>::SHAPE;
656 let arc_shape = <Arc<String>>::SHAPE;
657 let arc_def = arc_shape
658 .def
659 .into_pointer()
660 .expect("Arc<T> should have a smart pointer definition");
661
662 let arc_uninit_ptr = arc_shape.allocate().unwrap();
664 let new_into_fn = arc_def
665 .vtable
666 .new_into_fn
667 .expect("Arc<T> should have new_into_fn");
668
669 let mut value = String::from("try_into_inner test");
670 let arc_ptr = unsafe { new_into_fn(arc_uninit_ptr, PtrMut::new(&raw mut value)) };
671 core::mem::forget(value); let string_uninit_ptr = string_shape.allocate().unwrap();
675
676 let try_into_inner_fn = (arc_shape.vtable.sized().unwrap().try_into_inner)()
678 .expect("Arc<T> Shape should have try_into_inner");
679
680 let string_ptr = unsafe { try_into_inner_fn(arc_ptr, string_uninit_ptr) }
683 .expect("try_into_inner should succeed with exclusive access");
684
685 assert_eq!(
687 unsafe { string_ptr.as_const().get::<String>() },
688 "try_into_inner test"
689 );
690
691 let string_drop_fn = (string_shape.vtable.sized().unwrap().drop_in_place)()
693 .expect("String should have drop_in_place");
694
695 unsafe {
696 arc_shape.deallocate_mut(arc_ptr).unwrap();
699
700 string_drop_fn(string_ptr);
702 string_shape.deallocate_mut(string_ptr).unwrap();
703 }
704 }
705
706 #[test]
707 fn test_arc_vtable_6_slice_builder() {
708 facet_testhelpers::setup();
709
710 let arc_slice_shape = <Arc<[i32]>>::SHAPE;
712 let arc_slice_def = arc_slice_shape
713 .def
714 .into_pointer()
715 .expect("Arc<[i32]> should have a smart pointer definition");
716
717 let slice_builder_vtable = arc_slice_def
719 .vtable
720 .slice_builder_vtable
721 .expect("Arc<[i32]> should have slice_builder_vtable");
722
723 let builder_ptr = (slice_builder_vtable.new_fn)();
725
726 let push_fn = slice_builder_vtable.push_fn;
728 let values = [1i32, 2, 3, 4, 5];
729 for &value in &values {
730 let mut value_copy = value;
731 let value_ptr = PtrMut::new(&raw mut value_copy);
732 unsafe { push_fn(builder_ptr, value_ptr) };
733 let _ = value_copy; }
735
736 let convert_fn = slice_builder_vtable.convert_fn;
738 let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
739
740 let borrow_fn = arc_slice_def
742 .vtable
743 .borrow_fn
744 .expect("Arc<[i32]> should have borrow_fn");
745 let borrowed_ptr = unsafe { borrow_fn(arc_slice_ptr) };
746
747 let slice = unsafe { borrowed_ptr.get::<[i32]>() };
749 assert_eq!(slice, &[1, 2, 3, 4, 5]);
750
751 unsafe {
753 let _ = Box::from_raw(arc_slice_ptr.as_ptr::<Arc<[i32]>>() as *mut Arc<[i32]>);
754 }
755 }
756
757 #[test]
758 fn test_arc_vtable_7_slice_builder_free() {
759 facet_testhelpers::setup();
760
761 let arc_slice_shape = <Arc<[String]>>::SHAPE;
763 let arc_slice_def = arc_slice_shape
764 .def
765 .into_pointer()
766 .expect("Arc<[String]> should have a smart pointer definition");
767
768 let slice_builder_vtable = arc_slice_def
770 .vtable
771 .slice_builder_vtable
772 .expect("Arc<[String]> should have slice_builder_vtable");
773
774 let builder_ptr = (slice_builder_vtable.new_fn)();
776
777 let push_fn = slice_builder_vtable.push_fn;
779 let strings = ["hello", "world", "test"];
780 for &s in &strings {
781 let mut value = String::from(s);
782 let value_ptr = PtrMut::new(&raw mut value);
783 unsafe { push_fn(builder_ptr, value_ptr) };
784 core::mem::forget(value); }
786
787 let free_fn = slice_builder_vtable.free_fn;
790 unsafe { free_fn(builder_ptr) };
791
792 }
794}