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