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, 'shape, 'src, 'dst, T: Facet<'a>>(
15 src_ptr: PtrConst<'src>,
16 src_shape: &'shape Shape<'shape>,
17 dst: PtrUninit<'dst>,
18 ) -> Result<PtrMut<'dst>, TryFromError<'shape>> {
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<'static> = &const {
79 fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape<'static> {
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<'static> = &const {
139 fn inner_shape() -> &'static Shape<'static> {
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<'static> = &const {
193 fn inner_shape<'a, U: Facet<'a>>() -> &'static Shape<'static> {
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<'static> = &const {
286 fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape<'static> {
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<'static> = &const {
336 fn inner_shape() -> &'static Shape<'static> {
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<'static> = &const {
384 fn inner_shape<'a, U: Facet<'a>>() -> &'static Shape<'static> {
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() -> eyre::Result<()> {
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()?;
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)? };
479
480 Ok(())
481 }
482
483 #[test]
484 fn test_arc_vtable_2_downgrade_upgrade_drop() -> eyre::Result<()> {
485 facet_testhelpers::setup();
486
487 let arc_shape = <Arc<String>>::SHAPE;
488 let arc_def = arc_shape
489 .def
490 .into_pointer()
491 .expect("Arc<T> should have a smart pointer definition");
492
493 let weak_shape = <ArcWeak<String>>::SHAPE;
494 let weak_def = weak_shape
495 .def
496 .into_pointer()
497 .expect("ArcWeak<T> should have a smart pointer definition");
498
499 let arc1_uninit_ptr = arc_shape.allocate()?;
501 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
502 let mut value = String::from("example");
503 let arc1_ptr = unsafe { new_into_fn(arc1_uninit_ptr, PtrMut::new(&raw mut value)) };
504 core::mem::forget(value); let weak1_uninit_ptr = weak_shape.allocate()?;
508 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
509 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
511
512 let arc2_uninit_ptr = arc_shape.allocate()?;
514 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
515 let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
518 .expect("Upgrade should succeed while original Arc exists");
519
520 let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
522 let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
524 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
526
527 let arc_drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
529 let weak_drop_fn = (weak_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
530
531 unsafe {
532 arc_drop_fn(arc1_ptr);
534 arc_shape.deallocate_mut(arc1_ptr)?;
535 arc_drop_fn(arc2_ptr);
536 arc_shape.deallocate_mut(arc2_ptr)?;
537
538 weak_drop_fn(weak1_ptr);
540 weak_shape.deallocate_mut(weak1_ptr)?;
541 }
542
543 Ok(())
544 }
545
546 #[test]
547 fn test_arc_vtable_3_downgrade_drop_try_upgrade() -> eyre::Result<()> {
548 facet_testhelpers::setup();
549
550 let arc_shape = <Arc<String>>::SHAPE;
551 let arc_def = arc_shape
552 .def
553 .into_pointer()
554 .expect("Arc<T> should have a smart pointer definition");
555
556 let weak_shape = <ArcWeak<String>>::SHAPE;
557 let weak_def = weak_shape
558 .def
559 .into_pointer()
560 .expect("ArcWeak<T> should have a smart pointer definition");
561
562 let arc1_uninit_ptr = arc_shape.allocate()?;
564 let new_into_fn = arc_def.vtable.new_into_fn.unwrap();
565 let mut value = String::from("example");
566 let arc1_ptr = unsafe { new_into_fn(arc1_uninit_ptr, PtrMut::new(&raw mut value)) };
567 core::mem::forget(value);
568
569 let weak1_uninit_ptr = weak_shape.allocate()?;
571 let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
572 let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
574
575 let arc_drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
577 unsafe {
578 arc_drop_fn(arc1_ptr);
579 arc_shape.deallocate_mut(arc1_ptr)?;
580 }
581
582 let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
584 let arc2_uninit_ptr = arc_shape.allocate()?;
585 let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
587
588 assert!(
590 upgrade_result.is_none(),
591 "Upgrade should fail after the strong Arc is dropped"
592 );
593
594 let weak_drop_fn = (weak_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
596 unsafe {
597 arc_shape.deallocate_uninit(arc2_uninit_ptr)?;
599
600 weak_drop_fn(weak1_ptr);
602 weak_shape.deallocate_mut(weak1_ptr)?;
603 }
604
605 Ok(())
606 }
607
608 #[test]
609 fn test_arc_vtable_4_try_from() -> eyre::Result<()> {
610 facet_testhelpers::setup();
611
612 let string_shape = <String>::SHAPE;
614 let arc_shape = <Arc<String>>::SHAPE;
615 let arc_def = arc_shape
616 .def
617 .into_pointer()
618 .expect("Arc<T> should have a smart pointer definition");
619
620 let value = String::from("try_from test");
622 let value_ptr = PtrConst::new(&value as *const String as *const u8);
623
624 let arc_uninit_ptr = arc_shape.allocate()?;
626
627 let try_from_fn =
629 (arc_shape.vtable.sized().unwrap().try_from)().expect("Arc<T> should have try_from");
630
631 let arc_ptr = unsafe { try_from_fn(value_ptr, string_shape, arc_uninit_ptr) }
633 .expect("try_from should succeed");
634 core::mem::forget(value);
635
636 let borrow_fn = arc_def
638 .vtable
639 .borrow_fn
640 .expect("Arc<T> should have borrow_fn");
641 let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
642
643 assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "try_from test");
645
646 let drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)()
648 .expect("Arc<T> should have drop_in_place");
649
650 unsafe {
651 drop_fn(arc_ptr);
652 arc_shape.deallocate_mut(arc_ptr)?;
653 }
654
655 Ok(())
656 }
657
658 #[test]
659 fn test_arc_vtable_5_try_into_inner() -> eyre::Result<()> {
660 facet_testhelpers::setup();
661
662 let string_shape = <String>::SHAPE;
664 let arc_shape = <Arc<String>>::SHAPE;
665 let arc_def = arc_shape
666 .def
667 .into_pointer()
668 .expect("Arc<T> should have a smart pointer definition");
669
670 let arc_uninit_ptr = arc_shape.allocate()?;
672 let new_into_fn = arc_def
673 .vtable
674 .new_into_fn
675 .expect("Arc<T> should have new_into_fn");
676
677 let mut value = String::from("try_into_inner test");
678 let arc_ptr = unsafe { new_into_fn(arc_uninit_ptr, PtrMut::new(&raw mut value)) };
679 core::mem::forget(value); let string_uninit_ptr = string_shape.allocate()?;
683
684 let try_into_inner_fn = (arc_shape.vtable.sized().unwrap().try_into_inner)()
686 .expect("Arc<T> Shape should have try_into_inner");
687
688 let string_ptr = unsafe { try_into_inner_fn(arc_ptr, string_uninit_ptr) }
691 .expect("try_into_inner should succeed with exclusive access");
692
693 assert_eq!(
695 unsafe { string_ptr.as_const().get::<String>() },
696 "try_into_inner test"
697 );
698
699 let string_drop_fn = (string_shape.vtable.sized().unwrap().drop_in_place)()
701 .expect("String should have drop_in_place");
702
703 unsafe {
704 arc_shape.deallocate_mut(arc_ptr)?;
707
708 string_drop_fn(string_ptr);
710 string_shape.deallocate_mut(string_ptr)?;
711 }
712
713 Ok(())
714 }
715
716 #[test]
717 fn test_arc_vtable_6_slice_builder() -> eyre::Result<()> {
718 facet_testhelpers::setup();
719
720 let arc_slice_shape = <Arc<[i32]>>::SHAPE;
722 let arc_slice_def = arc_slice_shape
723 .def
724 .into_pointer()
725 .expect("Arc<[i32]> should have a smart pointer definition");
726
727 let slice_builder_vtable = arc_slice_def
729 .vtable
730 .slice_builder_vtable
731 .expect("Arc<[i32]> should have slice_builder_vtable");
732
733 let builder_ptr = (slice_builder_vtable.new_fn)();
735
736 let push_fn = slice_builder_vtable.push_fn;
738 let values = [1i32, 2, 3, 4, 5];
739 for &value in &values {
740 let mut value_copy = value;
741 let value_ptr = PtrMut::new(&raw mut value_copy);
742 unsafe { push_fn(builder_ptr, value_ptr) };
743 let _ = value_copy; }
745
746 let convert_fn = slice_builder_vtable.convert_fn;
748 let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
749
750 let borrow_fn = arc_slice_def
752 .vtable
753 .borrow_fn
754 .expect("Arc<[i32]> should have borrow_fn");
755 let borrowed_ptr = unsafe { borrow_fn(arc_slice_ptr) };
756
757 let slice = unsafe { borrowed_ptr.get::<[i32]>() };
759 assert_eq!(slice, &[1, 2, 3, 4, 5]);
760
761 unsafe {
763 let _ = Box::from_raw(arc_slice_ptr.as_ptr::<Arc<[i32]>>() as *mut Arc<[i32]>);
764 }
765
766 Ok(())
767 }
768
769 #[test]
770 fn test_arc_vtable_7_slice_builder_free() -> eyre::Result<()> {
771 facet_testhelpers::setup();
772
773 let arc_slice_shape = <Arc<[String]>>::SHAPE;
775 let arc_slice_def = arc_slice_shape
776 .def
777 .into_pointer()
778 .expect("Arc<[String]> should have a smart pointer definition");
779
780 let slice_builder_vtable = arc_slice_def
782 .vtable
783 .slice_builder_vtable
784 .expect("Arc<[String]> should have slice_builder_vtable");
785
786 let builder_ptr = (slice_builder_vtable.new_fn)();
788
789 let push_fn = slice_builder_vtable.push_fn;
791 let strings = ["hello", "world", "test"];
792 for &s in &strings {
793 let mut value = String::from(s);
794 let value_ptr = PtrMut::new(&raw mut value);
795 unsafe { push_fn(builder_ptr, value_ptr) };
796 core::mem::forget(value); }
798
799 let free_fn = slice_builder_vtable.free_fn;
802 unsafe { free_fn(builder_ptr) };
803
804 Ok(())
806 }
807}