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