facet_core/_trait/impls/
hashmap_impl.rs

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}