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}