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

facet-rs / facet / 14680246574

26 Apr 2025 10:13AM UTC coverage: 56.736% (+0.03%) from 56.703%
14680246574

push

github

fasterthanlime
Expose a typed VTable API, reduce unsafe code

124 of 288 new or added lines in 12 files covered. (43.06%)

3 existing lines in 3 files now uncovered.

6776 of 11943 relevant lines covered (56.74%)

74.65 hits per line

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

83.15
/facet-core/src/impls_std/hashmap.rs
1
use alloc::collections::VecDeque;
2
use core::hash::{BuildHasher, Hash};
3
use std::collections::HashMap;
4
use std::hash::RandomState;
5

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

8
use crate::{
9
    Def, Facet, MapDef, MapIterVTable, MapVTable, MarkerTraits, ScalarAffinity, ScalarDef, Shape,
10
    TypeParam, VTableView, ValueVTable, value_vtable,
11
};
12

13
struct HashMapIterator<'mem, K> {
14
    map: PtrConst<'mem>,
15
    keys: VecDeque<&'mem K>,
16
}
17

18
unsafe impl<'a, K, V, S> Facet<'a> for HashMap<K, V, S>
19
where
20
    K: Facet<'a> + core::cmp::Eq + core::hash::Hash,
21
    V: Facet<'a>,
22
    S: Facet<'a> + Default + BuildHasher,
23
{
24
    const SHAPE: &'static Shape = &const {
25
        Shape::builder_for_sized::<Self>()
26
            .type_params(&[
27
                TypeParam {
28
                    name: "K",
29
                    shape: || K::SHAPE,
1✔
30
                },
31
                TypeParam {
32
                    name: "V",
33
                    shape: || V::SHAPE,
1✔
34
                },
35
                TypeParam {
36
                    name: "S",
37
                    shape: || S::SHAPE,
1✔
38
                },
39
            ])
40
            .vtable(
41
                &const {
42
                    let mut builder = ValueVTable::builder::<Self>()
43
                        .marker_traits({
44
                            let arg_dependent_traits = MarkerTraits::SEND
45
                                .union(MarkerTraits::SYNC)
46
                                .union(MarkerTraits::EQ)
47
                                .union(MarkerTraits::UNPIN);
48
                            arg_dependent_traits
49
                                .intersection(V::SHAPE.vtable.marker_traits)
50
                                .intersection(K::SHAPE.vtable.marker_traits)
51
                        })
52
                        .type_name(|f, opts| {
7✔
53
                            if let Some(opts) = opts.for_children() {
7✔
54
                                write!(f, "HashMap<")?;
7✔
55
                                (K::SHAPE.vtable.type_name)(f, opts)?;
7✔
56
                                write!(f, ", ")?;
7✔
57
                                (V::SHAPE.vtable.type_name)(f, opts)?;
7✔
58
                                write!(f, ">")
7✔
59
                            } else {
60
                                write!(f, "HashMap<⋯>")
×
61
                            }
62
                        });
7✔
63

64
                    if K::SHAPE.vtable.debug.is_some() && V::SHAPE.vtable.debug.is_some() {
65
                        builder = builder.debug(|value, f| {
10✔
66
                            let k_debug = <VTableView<K>>::of().debug().unwrap();
10✔
67
                            let v_debug = <VTableView<V>>::of().debug().unwrap();
10✔
68
                            write!(f, "{{")?;
10✔
69
                            for (i, (key, val)) in value.iter().enumerate() {
16✔
70
                                if i > 0 {
16✔
71
                                    write!(f, ", ")?;
8✔
72
                                }
8✔
73
                                (k_debug)(key, f)?;
16✔
74
                                write!(f, ": ")?;
16✔
75
                                (v_debug)(val, f)?;
16✔
76
                            }
77
                            write!(f, "}}")
10✔
78
                        });
10✔
79
                    }
80

81
                    builder =
82
                        builder.default_in_place(|target| unsafe { target.put(Self::default()) });
26✔
83

84
                    // FIXME: THIS IS VERY WRONG
85
                    builder =
NEW
86
                        builder.clone_into(|src, dst| unsafe { dst.put(core::ptr::read(src)) });
×
87

88
                    if V::SHAPE.vtable.eq.is_some() {
89
                        builder = builder.eq(|a, b| {
2✔
90
                            let v_eq = <VTableView<V>>::of().eq().unwrap();
2✔
91
                            a.len() == b.len()
2✔
92
                                && a.iter().all(|(key_a, val_a)| {
3✔
93
                                    b.get(key_a).is_some_and(|val_b| (v_eq)(val_a, val_b))
3✔
94
                                })
3✔
95
                        });
2✔
96
                    }
97

98
                    if V::SHAPE.vtable.hash.is_some() {
99
                        builder = builder.hash(|map, hasher_this, hasher_write_fn| unsafe {
100
                            use crate::HasherProxy;
NEW
101
                            let v_hash = <VTableView<V>>::of().hash().unwrap();
×
102
                            let mut hasher = HasherProxy::new(hasher_this, hasher_write_fn);
×
103
                            map.len().hash(&mut hasher);
×
104
                            for (k, v) in map {
×
105
                                k.hash(&mut hasher);
×
NEW
106
                                (v_hash)(v, hasher_this, hasher_write_fn);
×
107
                            }
×
108
                        });
×
109
                    }
110

111
                    builder.build()
112
                },
113
            )
114
            .def(Def::Map(
115
                MapDef::builder()
116
                    .k(K::SHAPE)
117
                    .v(V::SHAPE)
118
                    .vtable(
119
                        &const {
120
                            MapVTable::builder()
121
                                .init_in_place_with_capacity(|uninit, capacity| unsafe {
×
122
                                    uninit
×
123
                                        .put(Self::with_capacity_and_hasher(capacity, S::default()))
×
124
                                })
×
125
                                .insert(|ptr, key, value| unsafe {
16✔
126
                                    let map = ptr.as_mut::<HashMap<K, V>>();
16✔
127
                                    let key = key.read::<K>();
16✔
128
                                    let value = value.read::<V>();
16✔
129
                                    map.insert(key, value);
16✔
130
                                })
16✔
131
                                .len(|ptr| unsafe {
5✔
132
                                    let map = ptr.get::<HashMap<K, V>>();
5✔
133
                                    map.len()
5✔
134
                                })
5✔
135
                                .contains_key(|ptr, key| unsafe {
8✔
136
                                    let map = ptr.get::<HashMap<K, V>>();
8✔
137
                                    map.contains_key(key.get())
8✔
138
                                })
8✔
139
                                .get_value_ptr(|ptr, key| unsafe {
8✔
140
                                    let map = ptr.get::<HashMap<K, V>>();
8✔
141
                                    map.get(key.get()).map(|v| PtrConst::new(v))
8✔
142
                                })
8✔
143
                                .iter(|ptr| unsafe {
5✔
144
                                    let map = ptr.get::<HashMap<K, V>>();
5✔
145
                                    let keys: VecDeque<&K> = map.keys().collect();
5✔
146
                                    let iter_state = Box::new(HashMapIterator { map: ptr, keys });
5✔
147
                                    PtrMut::new(Box::into_raw(iter_state) as *mut u8)
5✔
148
                                })
5✔
149
                                .iter_vtable(
150
                                    MapIterVTable::builder()
151
                                        .next(|iter_ptr| unsafe {
14✔
152
                                            let state = iter_ptr.as_mut::<HashMapIterator<'_, K>>();
14✔
153
                                            let map = state.map.get::<HashMap<K, V>>();
14✔
154
                                            while let Some(key) = state.keys.pop_front() {
14✔
155
                                                if let Some(value) = map.get(key) {
9✔
156
                                                    return Some((
9✔
157
                                                        PtrConst::new(key as *const K),
9✔
158
                                                        PtrConst::new(value as *const V),
9✔
159
                                                    ));
9✔
160
                                                }
×
161
                                            }
162

163
                                            None
5✔
164
                                        })
14✔
165
                                        .dealloc(|iter_ptr| unsafe {
5✔
166
                                            drop(Box::from_raw(
5✔
167
                                                iter_ptr.as_ptr::<HashMapIterator<'_, K>>()
5✔
168
                                                    as *mut HashMapIterator<'_, K>,
5✔
169
                                            ));
5✔
170
                                        })
5✔
171
                                        .build(),
172
                                )
173
                                .build()
174
                        },
175
                    )
176
                    .build(),
177
            ))
178
            .build()
179
    };
180
}
181

182
unsafe impl Facet<'_> for RandomState {
183
    const SHAPE: &'static Shape = &const {
184
        Shape::builder_for_sized::<Self>()
185
            .def(Def::Scalar(
186
                ScalarDef::builder()
187
                    .affinity(ScalarAffinity::opaque().build())
188
                    .build(),
189
            ))
190
            .vtable(&const { value_vtable!((), |f, _opts| write!(f, "RandomState")) })
1✔
191
            .build()
192
    };
193
}
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