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

facet-rs / facet / 19992174439

06 Dec 2025 05:56PM UTC coverage: 58.742% (-0.005%) from 58.747%
19992174439

Pull #1118

github

web-flow
Merge d1d251ac8 into 45a8cb1c3
Pull Request #1118: Reduce/cordon bloat in facet, introduce bloatbench

1138 of 3103 new or added lines in 61 files covered. (36.67%)

540 existing lines in 30 files now uncovered.

24225 of 41240 relevant lines covered (58.74%)

502.5 hits per line

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

88.89
/facet-core/src/impls_alloc/btreeset.rs
1
use core::ptr::NonNull;
2

3
use alloc::boxed::Box;
4
use alloc::collections::BTreeSet;
5

6
use crate::ptr::{PtrConst, PtrMut};
7

8
use crate::{Def, Facet, IterVTable, SetDef, SetVTable, ShapeBuilder, TypeParam, ValueVTable};
9

10
type BTreeSetIterator<'mem, T> = alloc::collections::btree_set::Iter<'mem, T>;
11

12
unsafe impl<'a, T> Facet<'a> for BTreeSet<T>
13
where
14
    T: Facet<'a> + core::cmp::Eq + core::cmp::Ord,
15
{
16
    const SHAPE: &'static crate::Shape = &const {
17
        ShapeBuilder::for_sized::<Self>(
18
            |f, opts| {
3✔
19
                write!(f, "{}<", Self::SHAPE.type_identifier)?;
3✔
20
                if let Some(opts) = opts.for_children() {
3✔
21
                    T::SHAPE.vtable.type_name()(f, opts)?;
3✔
22
                } else {
NEW
23
                    write!(f, "…")?;
×
24
                }
25
                write!(f, ">")
3✔
26
            },
3✔
27
            "BTreeSet",
28
        )
29
        .drop_in_place(ValueVTable::drop_in_place_for::<Self>())
NEW
30
        .default_in_place(|target| unsafe { target.put(Self::default()) })
×
31
        .def(Def::Set(SetDef::new(
32
            &const {
33
                SetVTable::new(
34
                    |uninit, _capacity| unsafe { uninit.put(Self::new()) },
7✔
35
                    |ptr, item| unsafe {
36
                        let set = ptr.as_mut::<BTreeSet<T>>();
25✔
37
                        let item = item.read::<T>();
25✔
38
                        set.insert(item)
25✔
39
                    },
25✔
40
                    |ptr| unsafe {
41
                        let set = ptr.get::<BTreeSet<T>>();
11✔
42
                        set.len()
11✔
43
                    },
11✔
44
                    |ptr, item| unsafe {
NEW
45
                        let set = ptr.get::<BTreeSet<T>>();
×
NEW
46
                        set.contains(item.get())
×
NEW
47
                    },
×
48
                    IterVTable {
49
                        init_with_value: Some(|ptr| {
4✔
50
                            let set = unsafe { ptr.get::<BTreeSet<T>>() };
4✔
51
                            let iter: BTreeSetIterator<'_, T> = set.iter();
4✔
52
                            let iter_state = Box::new(iter);
4✔
53
                            PtrMut::new(unsafe {
4✔
54
                                NonNull::new_unchecked(Box::into_raw(iter_state) as *mut u8)
4✔
55
                            })
56
                        }),
4✔
57
                        next: |iter_ptr| {
15✔
58
                            let state = unsafe { iter_ptr.as_mut::<BTreeSetIterator<'_, T>>() };
15✔
59
                            state
15✔
60
                                .next()
15✔
61
                                .map(|value| PtrConst::new(NonNull::from(value)))
15✔
62
                        },
15✔
NEW
63
                        next_back: Some(|iter_ptr| {
×
NEW
64
                            let state = unsafe { iter_ptr.as_mut::<BTreeSetIterator<'_, T>>() };
×
NEW
65
                            state
×
NEW
66
                                .next_back()
×
NEW
67
                                .map(|value| PtrConst::new(NonNull::from(value)))
×
NEW
68
                        }),
×
69
                        size_hint: None,
70
                        dealloc: |iter_ptr| unsafe {
71
                            drop(Box::from_raw(iter_ptr.as_ptr::<BTreeSetIterator<'_, T>>()
4✔
72
                                as *mut BTreeSetIterator<'_, T>));
4✔
73
                        },
4✔
74
                    },
75
                )
76
            },
77
            T::SHAPE,
78
        )))
79
        .type_params(&[TypeParam {
80
            name: "T",
81
            shape: T::SHAPE,
82
        }])
83
        .build()
84
    };
85
}
86

87
#[cfg(test)]
88
mod tests {
89
    use alloc::collections::BTreeSet;
90
    use alloc::string::String;
91
    use alloc::vec::Vec;
92

93
    use super::*;
94

95
    #[test]
96
    fn test_btreesetset_type_params() {
1✔
97
        let [type_param_1] = <BTreeSet<i32>>::SHAPE.type_params else {
1✔
98
            panic!("BTreeSet<T> should have 1 type param")
×
99
        };
100
        assert_eq!(type_param_1.shape(), i32::SHAPE);
1✔
101
    }
1✔
102

103
    #[test]
104
    fn test_btreeset_vtable_1_new_insert_iter_drop() {
1✔
105
        facet_testhelpers::setup();
1✔
106

107
        let btreeset_shape = <BTreeSet<String>>::SHAPE;
1✔
108
        let btreeset_def = btreeset_shape
1✔
109
            .def
1✔
110
            .into_set()
1✔
111
            .expect("BTreeSet<T> should have a set definition");
1✔
112

113
        // Allocate memory for the BTreeSet
114
        let btreeset_uninit_ptr = btreeset_shape.allocate().unwrap();
1✔
115

116
        // Create the BTreeSet
117
        let btreeset_ptr =
1✔
118
            unsafe { (btreeset_def.vtable.init_in_place_with_capacity_fn)(btreeset_uninit_ptr, 0) };
1✔
119

120
        // The BTreeSet is empty, so ensure its length is 0
121
        let btreeset_actual_length =
1✔
122
            unsafe { (btreeset_def.vtable.len_fn)(btreeset_ptr.as_const()) };
1✔
123
        assert_eq!(btreeset_actual_length, 0);
1✔
124

125
        // 5 sample values to insert
126
        let strings = ["foo", "bar", "bazz", "fizzbuzz", "fifth thing"];
1✔
127

128
        // Insert the 5 values into the BTreeSet
129
        let mut btreeset_length = 0;
1✔
130
        for string in strings {
5✔
131
            // Create the value
132
            let mut new_value = string.to_string();
5✔
133

134
            // Insert the value
135
            let did_insert = unsafe {
5✔
136
                (btreeset_def.vtable.insert_fn)(
5✔
137
                    btreeset_ptr,
5✔
138
                    PtrMut::new(NonNull::from(&mut new_value)),
5✔
139
                )
5✔
140
            };
141

142
            // The value now belongs to the BTreeSet, so forget it
143
            core::mem::forget(new_value);
5✔
144

145
            assert!(did_insert, "expected value to be inserted in the BTreeSet");
5✔
146

147
            // Ensure the BTreeSet's length increased by 1
148
            btreeset_length += 1;
5✔
149
            let btreeset_actual_length =
5✔
150
                unsafe { (btreeset_def.vtable.len_fn)(btreeset_ptr.as_const()) };
5✔
151
            assert_eq!(btreeset_actual_length, btreeset_length);
5✔
152
        }
153

154
        // Insert the same 5 values again, ensuring they are deduplicated
155
        for string in strings {
5✔
156
            // Create the value
157
            let mut new_value = string.to_string();
5✔
158

159
            // Try to insert the value
160
            let did_insert = unsafe {
5✔
161
                (btreeset_def.vtable.insert_fn)(
5✔
162
                    btreeset_ptr,
5✔
163
                    PtrMut::new(NonNull::from(&mut new_value)),
5✔
164
                )
5✔
165
            };
166

167
            // The value now belongs to the BTreeSet, so forget it
168
            core::mem::forget(new_value);
5✔
169

170
            assert!(
5✔
171
                !did_insert,
5✔
172
                "expected value to not be inserted in the BTreeSet"
173
            );
174

175
            // Ensure the BTreeSet's length did not increase
176
            let btreeset_actual_length =
5✔
177
                unsafe { (btreeset_def.vtable.len_fn)(btreeset_ptr.as_const()) };
5✔
178
            assert_eq!(btreeset_actual_length, btreeset_length);
5✔
179
        }
180

181
        // Create a new iterator over the BTreeSet
182
        let iter_init_with_value_fn = btreeset_def.vtable.iter_vtable.init_with_value.unwrap();
1✔
183
        let btreeset_iter_ptr = unsafe { iter_init_with_value_fn(btreeset_ptr.as_const()) };
1✔
184

185
        // Collect all the items from the BTreeSet's iterator
186
        let mut iter_items = Vec::<&str>::new();
1✔
187
        loop {
188
            // Get the next item from the iterator
189
            let item_ptr = unsafe { (btreeset_def.vtable.iter_vtable.next)(btreeset_iter_ptr) };
6✔
190
            let Some(item_ptr) = item_ptr else {
6✔
191
                break;
1✔
192
            };
193

194
            let item = unsafe { item_ptr.get::<String>() };
5✔
195

196
            // Add the item into the list of items returned from the iterator
197
            iter_items.push(&**item);
5✔
198
        }
199

200
        // Deallocate the iterator
201
        unsafe {
1✔
202
            (btreeset_def.vtable.iter_vtable.dealloc)(btreeset_iter_ptr);
1✔
203
        }
1✔
204

205
        // BTrees iterate in sorted order, so ensure the iterator returned
206
        // each item in order
207
        let mut strings_sorted = strings.to_vec();
1✔
208
        strings_sorted.sort();
1✔
209
        assert_eq!(iter_items, strings_sorted);
1✔
210

211
        // Get the function pointer for dropping the BTreeSet
212
        let drop_fn = btreeset_shape
1✔
213
            .vtable
1✔
214
            .drop_in_place
1✔
215
            .expect("BTreeSet<T> should have drop_in_place");
1✔
216

217
        // Drop the BTreeSet in place
218
        unsafe { drop_fn(btreeset_ptr) };
1✔
219

220
        // Deallocate the memory
221
        unsafe { btreeset_shape.deallocate_mut(btreeset_ptr).unwrap() };
1✔
222
    }
1✔
223
}
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