• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 15356076673

30 May 2025 09:25PM UTC coverage: 58.06% (-0.08%) from 58.142%
15356076673

Pull #687

github

web-flow
Merge ad60bff63 into c6bd2ccb8
Pull Request #687: Get rid of istates

2250 of 3416 new or added lines in 30 files covered. (65.87%)

375 existing lines in 29 files now uncovered.

10150 of 17482 relevant lines covered (58.06%)

128.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.14
/facet-core/src/impls_alloc/boxed.rs
1
use crate::{
2
    Def, Facet, KnownSmartPointer, PtrConst, PtrMut, PtrUninit, Shape, SmartPointerDef,
3
    SmartPointerFlags, SmartPointerVTable, TryBorrowInnerError, TryFromError, TryIntoInnerError,
4
    Type, UserType, ValueVTable, value_vtable,
5
};
6

7
unsafe impl<'a, T: Facet<'a>> Facet<'a> for alloc::boxed::Box<T> {
8
    const VTABLE: &'static ValueVTable = &const {
9
        // Define the functions for transparent conversion between Box<T> and T
UNCOV
10
        unsafe fn try_from<'a, 'shape, 'src, 'dst, T: Facet<'a>>(
×
UNCOV
11
            src_ptr: PtrConst<'src>,
×
UNCOV
12
            src_shape: &'shape Shape<'shape>,
×
UNCOV
13
            dst: PtrUninit<'dst>,
×
UNCOV
14
        ) -> Result<PtrMut<'dst>, TryFromError<'shape>> {
×
UNCOV
15
            if src_shape.id != T::SHAPE.id {
×
16
                return Err(TryFromError::UnsupportedSourceShape {
×
17
                    src_shape,
×
18
                    expected: &[T::SHAPE],
×
19
                });
×
UNCOV
20
            }
×
UNCOV
21
            let t = unsafe { src_ptr.read::<T>() };
×
UNCOV
22
            let boxed = alloc::boxed::Box::new(t);
×
UNCOV
23
            Ok(unsafe { dst.put(boxed) })
×
UNCOV
24
        }
×
25

26
        unsafe fn try_into_inner<'a, 'src, 'dst, T: Facet<'a>>(
×
27
            src_ptr: PtrMut<'src>,
×
28
            dst: PtrUninit<'dst>,
×
29
        ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
30
            let boxed = unsafe { src_ptr.read::<alloc::boxed::Box<T>>() };
×
31
            Ok(unsafe { dst.put(*boxed) })
×
32
        }
×
33

34
        unsafe fn try_borrow_inner<'a, 'src, T: Facet<'a>>(
×
35
            src_ptr: PtrConst<'src>,
×
36
        ) -> Result<PtrConst<'src>, TryBorrowInnerError> {
×
37
            let boxed = unsafe { src_ptr.get::<alloc::boxed::Box<T>>() };
×
38
            Ok(PtrConst::new(&**boxed))
×
39
        }
×
40

41
        let mut vtable = value_vtable!(alloc::boxed::Box<T>, |f, opts| {
38✔
42
            write!(f, "{}", Self::SHAPE.type_identifier)?;
38✔
43
            if let Some(opts) = opts.for_children() {
38✔
44
                write!(f, "<")?;
38✔
45
                (T::SHAPE.vtable.type_name)(f, opts)?;
38✔
46
                write!(f, ">")?;
38✔
47
            } else {
48
                write!(f, "<…>")?;
×
49
            }
50
            Ok(())
38✔
51
        });
38✔
UNCOV
52
        vtable.try_from = || Some(try_from::<T>);
×
53
        vtable.try_into_inner = || Some(try_into_inner::<T>);
×
54
        vtable.try_borrow_inner = || Some(try_borrow_inner::<T>);
×
55
        vtable
56
    };
57

58
    const SHAPE: &'static crate::Shape<'static> = &const {
59
        // Function to return inner type's shape
UNCOV
60
        fn inner_shape<'a, T: Facet<'a>>() -> &'static Shape<'static> {
×
UNCOV
61
            T::SHAPE
×
UNCOV
62
        }
×
63

64
        crate::Shape::builder_for_sized::<Self>()
65
            .type_identifier("Box")
66
            .type_params(&[crate::TypeParam {
67
                name: "T",
68
                shape: || T::SHAPE,
69
            }])
70
            .ty(Type::User(UserType::Opaque))
71
            .def(Def::SmartPointer(
72
                SmartPointerDef::builder()
73
                    .pointee(|| T::SHAPE)
74
                    .flags(SmartPointerFlags::EMPTY)
75
                    .known(KnownSmartPointer::Box)
76
                    .vtable(
77
                        &const {
78
                            SmartPointerVTable::builder()
79
                                .borrow_fn(|this| {
6✔
80
                                    let ptr = unsafe {
6✔
81
                                        &raw const **this.as_ptr::<alloc::boxed::Box<T>>()
6✔
82
                                    };
83
                                    PtrConst::new(ptr)
6✔
84
                                })
6✔
85
                                .new_into_fn(|this, ptr| {
10✔
86
                                    let t = unsafe { ptr.read::<T>() };
10✔
87
                                    let boxed = alloc::boxed::Box::new(t);
10✔
88
                                    unsafe { this.put(boxed) }
10✔
89
                                })
10✔
90
                                .build()
91
                        },
92
                    )
93
                    .build(),
94
            ))
95
            .inner(inner_shape::<T>)
96
            .build()
97
    };
98
}
99

100
#[cfg(test)]
101
mod tests {
102
    use alloc::boxed::Box;
103
    use alloc::string::String;
104

105
    use super::*;
106

107
    #[test]
108
    fn test_box_type_params() {
1✔
109
        let [type_param_1] = <Box<i32>>::SHAPE.type_params else {
1✔
110
            panic!("Box<T> should only have 1 type param")
×
111
        };
112
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
113
    }
1✔
114

115
    #[test]
116
    fn test_box_vtable_1_new_borrow_drop() -> eyre::Result<()> {
1✔
117
        facet_testhelpers::setup();
1✔
118

119
        let box_shape = <Box<String>>::SHAPE;
1✔
120
        let box_def = box_shape
1✔
121
            .def
1✔
122
            .into_smart_pointer()
1✔
123
            .expect("Box<T> should have a smart pointer definition");
1✔
124

125
        // Allocate memory for the Box
126
        let box_uninit_ptr = box_shape.allocate()?;
1✔
127

128
        // Get the function pointer for creating a new Box from a value
129
        let new_into_fn = box_def
1✔
130
            .vtable
1✔
131
            .new_into_fn
1✔
132
            .expect("Box<T> should have new_into_fn");
1✔
133

134
        // Create the value and initialize the Box
135
        let mut value = String::from("example");
1✔
136
        let box_ptr = unsafe { new_into_fn(box_uninit_ptr, PtrMut::new(&raw mut value)) };
1✔
137
        // The value now belongs to the Box, prevent its drop
138
        core::mem::forget(value);
1✔
139

140
        // Get the function pointer for borrowing the inner value
141
        let borrow_fn = box_def
1✔
142
            .vtable
1✔
143
            .borrow_fn
1✔
144
            .expect("Box<T> should have borrow_fn");
1✔
145

146
        // Borrow the inner value and check it
147
        let borrowed_ptr = unsafe { borrow_fn(box_ptr.as_const()) };
1✔
148
        // SAFETY: borrowed_ptr points to a valid String within the Box
149
        assert_eq!(unsafe { borrowed_ptr.get::<String>() }, "example");
1✔
150

151
        // Get the function pointer for dropping the Box
152
        let drop_fn = (box_shape.vtable.drop_in_place)().expect("Box<T> should have drop_in_place");
1✔
153

154
        // Drop the Box in place
155
        // SAFETY: box_ptr points to a valid Box<String>
156
        unsafe { drop_fn(box_ptr) };
1✔
157

158
        // Deallocate the memory
159
        // SAFETY: box_ptr was allocated by box_shape and is now dropped (but memory is still valid)
160
        unsafe { box_shape.deallocate_mut(box_ptr)? };
1✔
161

162
        Ok(())
1✔
163
    }
1✔
164
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc