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