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}