facet_trait/impls/
hashmap_impl.rs

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                    // Hash length and entries
117                    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}