facet_core/_trait/impls/
hashmap_impl.rs

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}