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