facet_core/impls_alloc/
arc.rs

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        // Define the functions for transparent conversion between Arc<T> and T
14        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            // Read the Arc from the source pointer
37            let arc = unsafe { src_ptr.read::<Arc<T>>() };
38
39            // Try to unwrap the Arc to get exclusive ownership
40            match Arc::try_unwrap(arc) {
41                Ok(inner) => Ok(unsafe { dst.put(inner) }),
42                Err(arc) => {
43                    // Arc is shared, so we can't extract the inner value
44                    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        // Function to return inner type's shape
80        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        // Function to return inner type's shape
140        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        // Function to return inner type's shape
194        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        // Function to return inner type's shape
287        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        // Function to return inner type's shape
337        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        // Allocate memory for the Arc
443        let arc_uninit_ptr = arc_shape.allocate()?;
444
445        // Get the function pointer for creating a new Arc from a value
446        let new_into_fn = arc_def
447            .vtable
448            .new_into_fn
449            .expect("Arc<T> should have new_into_fn");
450
451        // Create the value and initialize the Arc
452        let mut value = String::from("example");
453        let arc_ptr = unsafe { new_into_fn(arc_uninit_ptr, PtrMut::new(&raw mut value)) };
454        // The value now belongs to the Arc, prevent its drop
455        core::mem::forget(value);
456
457        // Get the function pointer for borrowing the inner value
458        let borrow_fn = arc_def
459            .vtable
460            .borrow_fn
461            .expect("Arc<T> should have borrow_fn");
462
463        // Borrow the inner value and check it
464        let borrowed_ptr = unsafe { borrow_fn(arc_ptr.as_const()) };
465        // SAFETY: borrowed_ptr points to a valid String within the Arc
466        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
467
468        // Get the function pointer for dropping the Arc
469        let drop_fn = (arc_shape.vtable.sized().unwrap().drop_in_place)()
470            .expect("Arc<T> should have drop_in_place");
471
472        // Drop the Arc in place
473        // SAFETY: arc_ptr points to a valid Arc<String>
474        unsafe { drop_fn(arc_ptr) };
475
476        // Deallocate the memory
477        // SAFETY: arc_ptr was allocated by arc_shape and is now dropped (but memory is still valid)
478        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        // 1. Create the first Arc (arc1)
500        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); // Value now owned by arc1
505
506        // 2. Downgrade arc1 to create a weak pointer (weak1)
507        let weak1_uninit_ptr = weak_shape.allocate()?;
508        let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
509        // SAFETY: arc1_ptr points to a valid Arc, weak1_uninit_ptr is allocated for a Weak
510        let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
511
512        // 3. Upgrade weak1 to create a second Arc (arc2)
513        let arc2_uninit_ptr = arc_shape.allocate()?;
514        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
515        // SAFETY: weak1_ptr points to a valid Weak, arc2_uninit_ptr is allocated for an Arc.
516        // Upgrade should succeed as arc1 still exists.
517        let arc2_ptr = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) }
518            .expect("Upgrade should succeed while original Arc exists");
519
520        // Check the content of the upgraded Arc
521        let borrow_fn = arc_def.vtable.borrow_fn.unwrap();
522        // SAFETY: arc2_ptr points to a valid Arc<String>
523        let borrowed_ptr = unsafe { borrow_fn(arc2_ptr.as_const()) };
524        // SAFETY: borrowed_ptr points to a valid String
525        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
526
527        // 4. Drop everything and free memory
528        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            // Drop Arcs
533            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            // Drop Weak
539            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        // 1. Create the strong Arc (arc1)
563        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        // 2. Downgrade arc1 to create a weak pointer (weak1)
570        let weak1_uninit_ptr = weak_shape.allocate()?;
571        let downgrade_into_fn = arc_def.vtable.downgrade_into_fn.unwrap();
572        // SAFETY: arc1_ptr is valid, weak1_uninit_ptr is allocated for Weak
573        let weak1_ptr = unsafe { downgrade_into_fn(arc1_ptr, weak1_uninit_ptr) };
574
575        // 3. Drop and free the strong pointer (arc1)
576        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        // 4. Attempt to upgrade the weak pointer (weak1)
583        let upgrade_into_fn = weak_def.vtable.upgrade_into_fn.unwrap();
584        let arc2_uninit_ptr = arc_shape.allocate()?;
585        // SAFETY: weak1_ptr is valid (though points to dropped data), arc2_uninit_ptr is allocated for Arc
586        let upgrade_result = unsafe { upgrade_into_fn(weak1_ptr, arc2_uninit_ptr) };
587
588        // Assert that the upgrade failed
589        assert!(
590            upgrade_result.is_none(),
591            "Upgrade should fail after the strong Arc is dropped"
592        );
593
594        // 5. Clean up: Deallocate the memory intended for the failed upgrade and drop/deallocate the weak pointer
595        let weak_drop_fn = (weak_shape.vtable.sized().unwrap().drop_in_place)().unwrap();
596        unsafe {
597            // Deallocate the *uninitialized* memory allocated for the failed upgrade attempt
598            arc_shape.deallocate_uninit(arc2_uninit_ptr)?;
599
600            // Drop and deallocate the weak pointer
601            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        // Get the shapes we'll be working with
613        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        // 1. Create a String value
621        let value = String::from("try_from test");
622        let value_ptr = PtrConst::new(&value as *const String as *const u8);
623
624        // 2. Allocate memory for the Arc<String>
625        let arc_uninit_ptr = arc_shape.allocate()?;
626
627        // 3. Get the try_from function from the Arc<String> shape's ValueVTable
628        let try_from_fn =
629            (arc_shape.vtable.sized().unwrap().try_from)().expect("Arc<T> should have try_from");
630
631        // 4. Try to convert String to Arc<String>
632        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        // 5. Borrow the inner value and verify it's correct
637        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        // SAFETY: borrowed_ptr points to a valid String within the Arc
644        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "try_from test");
645
646        // 6. Clean up
647        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        // Get the shapes we'll be working with
663        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        // 1. Create an Arc<String>
671        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); // Value now owned by arc
680
681        // 2. Allocate memory for the extracted String
682        let string_uninit_ptr = string_shape.allocate()?;
683
684        // 3. Get the try_into_inner function from the Arc<String>'s ValueVTable
685        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        // 4. Try to extract the String from the Arc<String>
689        // This should succeed because we have exclusive access to the Arc (strong count = 1)
690        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        // 5. Verify the extracted String
694        assert_eq!(
695            unsafe { string_ptr.as_const().get::<String>() },
696            "try_into_inner test"
697        );
698
699        // 6. Clean up
700        let string_drop_fn = (string_shape.vtable.sized().unwrap().drop_in_place)()
701            .expect("String should have drop_in_place");
702
703        unsafe {
704            // The Arc should already be dropped by try_into_inner
705            // But we still need to deallocate its memory
706            arc_shape.deallocate_mut(arc_ptr)?;
707
708            // Drop and deallocate the extracted String
709            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        // Get the shapes we'll be working with
721        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        // Get the slice builder vtable
728        let slice_builder_vtable = arc_slice_def
729            .vtable
730            .slice_builder_vtable
731            .expect("Arc<[i32]> should have slice_builder_vtable");
732
733        // 1. Create a new builder
734        let builder_ptr = (slice_builder_vtable.new_fn)();
735
736        // 2. Push some items to the builder
737        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; // Value now owned by the builder
744        }
745
746        // 3. Convert the builder to Arc<[i32]>
747        let convert_fn = slice_builder_vtable.convert_fn;
748        let arc_slice_ptr = unsafe { convert_fn(builder_ptr) };
749
750        // 4. Verify the contents by borrowing
751        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        // Convert the wide pointer to a slice reference
758        let slice = unsafe { borrowed_ptr.get::<[i32]>() };
759        assert_eq!(slice, &[1, 2, 3, 4, 5]);
760
761        // 5. Clean up - the Arc<[i32]> was boxed by convert_fn, we need to deallocate the Box
762        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        // Get the shapes we'll be working with
774        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        // Get the slice builder vtable
781        let slice_builder_vtable = arc_slice_def
782            .vtable
783            .slice_builder_vtable
784            .expect("Arc<[String]> should have slice_builder_vtable");
785
786        // 1. Create a new builder
787        let builder_ptr = (slice_builder_vtable.new_fn)();
788
789        // 2. Push some items to the builder
790        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); // Value now owned by the builder
797        }
798
799        // 3. Instead of converting, test the free function
800        // This simulates abandoning the builder without creating the Arc
801        let free_fn = slice_builder_vtable.free_fn;
802        unsafe { free_fn(builder_ptr) };
803
804        // If we get here without panicking, the free worked correctly
805        Ok(())
806    }
807}