1use alloc::collections::VecDeque;
2use core::{alloc::Layout, hash::Hash};
3use std::collections::HashMap;
4use std::hash::RandomState;
5
6use crate::ptr::{PtrConst, PtrMut};
7
8use crate::{
9 ConstTypeId, Def, Facet, MapDef, MapIterVTable, MapVTable, MarkerTraits, ScalarAffinity,
10 ScalarDef, Shape, TypeParam, ValueVTable, value_vtable,
11};
12
13struct HashMapIterator<'mem, K> {
14 map: PtrConst<'mem>,
15 keys: VecDeque<&'mem K>,
16}
17
18unsafe impl<'a, K, V, S> Facet<'a> for HashMap<K, V, S>
19where
20 K: Facet<'a> + core::cmp::Eq + core::hash::Hash,
21 V: Facet<'a>,
22 S: Facet<'a> + Default,
23{
24 const SHAPE: &'static Shape = &const {
25 Shape::builder()
26 .id(ConstTypeId::of::<HashMap<K, V, S>>())
27 .layout(Layout::new::<HashMap<K, V>>())
28 .type_params(&[
29 TypeParam {
30 name: "K",
31 shape: || K::SHAPE,
32 },
33 TypeParam {
34 name: "V",
35 shape: || V::SHAPE,
36 },
37 TypeParam {
38 name: "S",
39 shape: || S::SHAPE,
40 },
41 ])
42 .vtable(
43 &const {
44 let mut builder = ValueVTable::builder()
45 .marker_traits({
46 let arg_dependent_traits = MarkerTraits::SEND
47 .union(MarkerTraits::SYNC)
48 .union(MarkerTraits::EQ)
49 .union(MarkerTraits::UNPIN);
50 arg_dependent_traits
51 .intersection(V::SHAPE.vtable.marker_traits)
52 .intersection(K::SHAPE.vtable.marker_traits)
53 })
54 .type_name(|f, opts| {
55 if let Some(opts) = opts.for_children() {
56 write!(f, "HashMap<")?;
57 (K::SHAPE.vtable.type_name)(f, opts)?;
58 write!(f, ", ")?;
59 (V::SHAPE.vtable.type_name)(f, opts)?;
60 write!(f, ">")
61 } else {
62 write!(f, "HashMap<⋯>")
63 }
64 })
65 .drop_in_place(|value| unsafe { value.drop_in_place::<HashMap<K, V>>() });
66
67 if K::SHAPE.vtable.debug.is_some() && V::SHAPE.vtable.debug.is_some() {
68 builder = builder.debug(|value, f| unsafe {
69 let value = value.get::<HashMap<K, V>>();
70 let k_debug = K::SHAPE.vtable.debug.unwrap_unchecked();
71 let v_debug = V::SHAPE.vtable.debug.unwrap_unchecked();
72 write!(f, "{{")?;
73 for (i, (key, val)) in value.iter().enumerate() {
74 if i > 0 {
75 write!(f, ", ")?;
76 }
77 (k_debug)(PtrConst::new(key as *const _), f)?;
78 write!(f, ": ")?;
79 (v_debug)(PtrConst::new(val as *const _), f)?;
80 }
81 write!(f, "}}")
82 });
83 }
84
85 builder =
86 builder.default_in_place(|target| unsafe { target.put(Self::default()) });
87
88 builder = builder
89 .clone_into(|src, dst| unsafe { dst.put(src.get::<HashMap<K, V>>()) });
90
91 if V::SHAPE.vtable.eq.is_some() {
92 builder = builder.eq(|a, b| unsafe {
93 let a = a.get::<HashMap<K, V>>();
94 let b = b.get::<HashMap<K, V>>();
95 let v_eq = V::SHAPE.vtable.eq.unwrap_unchecked();
96 a.len() == b.len()
97 && a.iter().all(|(key_a, val_a)| {
98 b.get(key_a).is_some_and(|val_b| {
99 (v_eq)(
100 PtrConst::new(val_a as *const _),
101 PtrConst::new(val_b as *const _),
102 )
103 })
104 })
105 });
106 }
107
108 if V::SHAPE.vtable.hash.is_some() {
109 builder = builder.hash(|value, hasher_this, hasher_write_fn| unsafe {
110 use crate::HasherProxy;
111 let map = value.get::<HashMap<K, V>>();
112 let v_hash = V::SHAPE.vtable.hash.unwrap_unchecked();
113 let mut hasher = HasherProxy::new(hasher_this, hasher_write_fn);
114 map.len().hash(&mut hasher);
115 for (k, v) in map {
116 k.hash(&mut hasher);
117 (v_hash)(
118 PtrConst::new(v as *const _),
119 hasher_this,
120 hasher_write_fn,
121 );
122 }
123 });
124 }
125
126 builder.build()
127 },
128 )
129 .def(Def::Map(
130 MapDef::builder()
131 .k(K::SHAPE)
132 .v(V::SHAPE)
133 .vtable(
134 &const {
135 MapVTable::builder()
136 .init_in_place_with_capacity(|uninit, capacity| unsafe {
137 uninit
138 .put(Self::with_capacity_and_hasher(capacity, S::default()))
139 })
140 .insert(|ptr, key, value| unsafe {
141 let map = ptr.as_mut::<HashMap<K, V>>();
142 let key = key.read::<K>();
143 let value = value.read::<V>();
144 map.insert(key, value);
145 })
146 .len(|ptr| unsafe {
147 let map = ptr.get::<HashMap<K, V>>();
148 map.len()
149 })
150 .contains_key(|ptr, key| unsafe {
151 let map = ptr.get::<HashMap<K, V>>();
152 map.contains_key(key.get())
153 })
154 .get_value_ptr(|ptr, key| unsafe {
155 let map = ptr.get::<HashMap<K, V>>();
156 map.get(key.get()).map(|v| PtrConst::new(v as *const _))
157 })
158 .iter(|ptr| unsafe {
159 let map = ptr.get::<HashMap<K, V>>();
160 let keys: VecDeque<&K> = map.keys().collect();
161 let iter_state = Box::new(HashMapIterator { map: ptr, keys });
162 PtrMut::new(Box::into_raw(iter_state) as *mut u8)
163 })
164 .iter_vtable(
165 MapIterVTable::builder()
166 .next(|iter_ptr| unsafe {
167 let state = iter_ptr.as_mut::<HashMapIterator<'_, K>>();
168 let map = state.map.get::<HashMap<K, V>>();
169 while let Some(key) = state.keys.pop_front() {
170 if let Some(value) = map.get(key) {
171 return Some((
172 PtrConst::new(key as *const K),
173 PtrConst::new(value as *const V),
174 ));
175 }
176 }
177
178 None
179 })
180 .dealloc(|iter_ptr| unsafe {
181 drop(Box::from_raw(
182 iter_ptr.as_ptr::<HashMapIterator<'_, K>>()
183 as *mut HashMapIterator<'_, K>,
184 ));
185 })
186 .build(),
187 )
188 .build()
189 },
190 )
191 .build(),
192 ))
193 .build()
194 };
195}
196
197unsafe impl Facet<'_> for RandomState {
198 const SHAPE: &'static Shape = &const {
199 Shape::builder()
200 .id(ConstTypeId::of::<RandomState>())
201 .layout(Layout::new::<Self>())
202 .def(Def::Scalar(
203 ScalarDef::builder()
204 .affinity(ScalarAffinity::opaque().build())
205 .build(),
206 ))
207 .vtable(value_vtable!((), |f, _opts| write!(f, "RandomState")))
208 .build()
209 };
210}