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}