facet_core/impls_std/
hashmap.rs

1use core::hash::{BuildHasher, Hash};
2use std::collections::HashMap;
3use std::hash::RandomState;
4
5use crate::ptr::{PtrConst, PtrMut};
6
7use crate::{
8    Def, Facet, IterVTable, MapDef, MapVTable, MarkerTraits, ScalarAffinity, ScalarDef, Shape,
9    Type, TypeParam, UserType, VTableView, ValueVTable, value_vtable,
10};
11
12type HashMapIterator<'mem, K, V> = std::collections::hash_map::Iter<'mem, K, V>;
13
14unsafe impl<'a, K, V, S> Facet<'a> for HashMap<K, V, S>
15where
16    K: Facet<'a> + core::cmp::Eq + core::hash::Hash,
17    V: Facet<'a>,
18    S: Facet<'a> + Default + BuildHasher,
19{
20    const VTABLE: &'static ValueVTable = &const {
21        let mut builder = ValueVTable::builder::<Self>()
22            .marker_traits({
23                let arg_dependent_traits = MarkerTraits::SEND
24                    .union(MarkerTraits::SYNC)
25                    .union(MarkerTraits::EQ)
26                    .union(MarkerTraits::UNPIN);
27                arg_dependent_traits
28                    .intersection(V::SHAPE.vtable.marker_traits)
29                    .intersection(K::SHAPE.vtable.marker_traits)
30            })
31            .type_name(|f, opts| {
32                if let Some(opts) = opts.for_children() {
33                    write!(f, "HashMap<")?;
34                    (K::SHAPE.vtable.type_name)(f, opts)?;
35                    write!(f, ", ")?;
36                    (V::SHAPE.vtable.type_name)(f, opts)?;
37                    write!(f, ">")
38                } else {
39                    write!(f, "HashMap<⋯>")
40                }
41            });
42
43        if K::SHAPE.vtable.debug.is_some() && V::SHAPE.vtable.debug.is_some() {
44            builder = builder.debug(|value, f| {
45                let k_debug = <VTableView<K>>::of().debug().unwrap();
46                let v_debug = <VTableView<V>>::of().debug().unwrap();
47                write!(f, "{{")?;
48                for (i, (key, val)) in value.iter().enumerate() {
49                    if i > 0 {
50                        write!(f, ", ")?;
51                    }
52                    (k_debug)(key, f)?;
53                    write!(f, ": ")?;
54                    (v_debug)(val, f)?;
55                }
56                write!(f, "}}")
57            });
58        }
59
60        builder = builder.default_in_place(|target| unsafe { target.put(Self::default()) });
61
62        if V::SHAPE.vtable.clone_into.is_some() && K::SHAPE.vtable.clone_into.is_some() {
63            builder = builder.clone_into(|src, dst| unsafe {
64                let map = src;
65                let mut new_map = HashMap::with_capacity_and_hasher(map.len(), S::default());
66
67                let k_clone_into = <VTableView<K>>::of().clone_into().unwrap();
68                let v_clone_into = <VTableView<V>>::of().clone_into().unwrap();
69
70                for (k, v) in map {
71                    use crate::TypedPtrUninit;
72                    use core::mem::MaybeUninit;
73
74                    let mut new_k = MaybeUninit::<K>::uninit();
75                    let mut new_v = MaybeUninit::<V>::uninit();
76
77                    let uninit_k = TypedPtrUninit::new(new_k.as_mut_ptr());
78                    let uninit_v = TypedPtrUninit::new(new_v.as_mut_ptr());
79
80                    (k_clone_into)(k, uninit_k);
81                    (v_clone_into)(v, uninit_v);
82
83                    new_map.insert(new_k.assume_init(), new_v.assume_init());
84                }
85
86                dst.put(new_map)
87            });
88        }
89
90        if V::SHAPE.vtable.eq.is_some() {
91            builder = builder.eq(|a, b| {
92                let v_eq = <VTableView<V>>::of().eq().unwrap();
93                a.len() == b.len()
94                    && a.iter().all(|(key_a, val_a)| {
95                        b.get(key_a).is_some_and(|val_b| (v_eq)(val_a, val_b))
96                    })
97            });
98        }
99
100        if V::SHAPE.vtable.hash.is_some() {
101            builder = builder.hash(|map, hasher_this, hasher_write_fn| unsafe {
102                use crate::HasherProxy;
103                let v_hash = <VTableView<V>>::of().hash().unwrap();
104                let mut hasher = HasherProxy::new(hasher_this, hasher_write_fn);
105                map.len().hash(&mut hasher);
106                for (k, v) in map {
107                    k.hash(&mut hasher);
108                    (v_hash)(v, hasher_this, hasher_write_fn);
109                }
110            });
111        }
112
113        builder.build()
114    };
115
116    const SHAPE: &'static Shape<'static> = &const {
117        Shape::builder_for_sized::<Self>()
118            .type_params(&[
119                TypeParam {
120                    name: "K",
121                    shape: || K::SHAPE,
122                },
123                TypeParam {
124                    name: "V",
125                    shape: || V::SHAPE,
126                },
127                TypeParam {
128                    name: "S",
129                    shape: || S::SHAPE,
130                },
131            ])
132            .ty(Type::User(UserType::Opaque))
133            .def(Def::Map(
134                MapDef::builder()
135                    .k(|| K::SHAPE)
136                    .v(|| V::SHAPE)
137                    .vtable(
138                        &const {
139                            MapVTable::builder()
140                                .init_in_place_with_capacity(|uninit, capacity| unsafe {
141                                    uninit
142                                        .put(Self::with_capacity_and_hasher(capacity, S::default()))
143                                })
144                                .insert(|ptr, key, value| unsafe {
145                                    let map = ptr.as_mut::<HashMap<K, V>>();
146                                    let key = key.read::<K>();
147                                    let value = value.read::<V>();
148                                    map.insert(key, value);
149                                })
150                                .len(|ptr| unsafe {
151                                    let map = ptr.get::<HashMap<K, V>>();
152                                    map.len()
153                                })
154                                .contains_key(|ptr, key| unsafe {
155                                    let map = ptr.get::<HashMap<K, V>>();
156                                    map.contains_key(key.get())
157                                })
158                                .get_value_ptr(|ptr, key| unsafe {
159                                    let map = ptr.get::<HashMap<K, V>>();
160                                    map.get(key.get()).map(|v| PtrConst::new(v))
161                                })
162                                .iter_vtable(
163                                    IterVTable::builder()
164                                        .init_with_value(|ptr| unsafe {
165                                            let map = ptr.get::<HashMap<K, V>>();
166                                            let iter: HashMapIterator<'_, K, V> = map.iter();
167                                            let iter_state = Box::new(iter);
168                                            PtrMut::new(Box::into_raw(iter_state) as *mut u8)
169                                        })
170                                        .next(|iter_ptr| unsafe {
171                                            let state =
172                                                iter_ptr.as_mut::<HashMapIterator<'_, K, V>>();
173                                            state.next().map(|(key, value)| {
174                                                (
175                                                    PtrConst::new(key as *const K),
176                                                    PtrConst::new(value as *const V),
177                                                )
178                                            })
179                                        })
180                                        .dealloc(|iter_ptr| unsafe {
181                                            drop(Box::from_raw(
182                                                iter_ptr.as_ptr::<HashMapIterator<'_, K, V>>()
183                                                    as *mut HashMapIterator<'_, K, V>,
184                                            ));
185                                        })
186                                        .build(),
187                                )
188                                .build()
189                        },
190                    )
191                    .build(),
192            ))
193            .build()
194    };
195}
196
197unsafe impl Facet<'_> for RandomState {
198    const VTABLE: &'static ValueVTable =
199        &const { value_vtable!((), |f, _opts| write!(f, "RandomState")) };
200
201    const SHAPE: &'static Shape<'static> = &const {
202        Shape::builder_for_sized::<Self>()
203            .ty(Type::User(UserType::Opaque))
204            .def(Def::Scalar(
205                ScalarDef::builder()
206                    .affinity(&const { ScalarAffinity::opaque().build() })
207                    .build(),
208            ))
209            .build()
210    };
211}