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