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