facet_core/impls_std/
hashmap.rs

1use core::hash::BuildHasher;
2use core::ptr::NonNull;
3use std::collections::HashMap;
4use std::hash::RandomState;
5
6use crate::ptr::{PtrConst, PtrMut};
7
8use crate::{
9    Def, Facet, IterVTable, MapDef, MapVTable, MarkerTraits, Shape, Type, TypeParam, UserType,
10    ValueVTable, value_vtable,
11};
12
13type HashMapIterator<'mem, K, V> = std::collections::hash_map::Iter<'mem, K, V>;
14
15// TODO: Debug, PartialEq, Eq for HashMap, HashSet
16unsafe impl<'a, K, V, S> Facet<'a> for HashMap<K, V, S>
17where
18    K: Facet<'a> + core::cmp::Eq + core::hash::Hash,
19    V: Facet<'a>,
20    S: 'a + Default + BuildHasher,
21{
22    const SHAPE: &'static Shape = &const {
23        Shape::builder_for_sized::<Self>()
24            .vtable(
25                ValueVTable::builder::<Self>()
26                    .marker_traits({
27                        let arg_dependent_traits = MarkerTraits::SEND
28                            .union(MarkerTraits::SYNC)
29                            .union(MarkerTraits::EQ)
30                            .union(MarkerTraits::UNPIN)
31                            .union(MarkerTraits::UNWIND_SAFE)
32                            .union(MarkerTraits::REF_UNWIND_SAFE);
33                        arg_dependent_traits
34                            .intersection(V::SHAPE.vtable.marker_traits())
35                            .intersection(K::SHAPE.vtable.marker_traits())
36                    })
37                    .type_name(|f, opts| {
38                        write!(f, "{}<", Self::SHAPE.type_identifier)?;
39                        if let Some(opts) = opts.for_children() {
40                            K::SHAPE.vtable.type_name()(f, opts)?;
41                            write!(f, ", ")?;
42                            V::SHAPE.vtable.type_name()(f, opts)?;
43                        } else {
44                            write!(f, "…")?;
45                        }
46                        write!(f, ">")
47                    })
48                    .default_in_place({
49                        Some(|target| unsafe { target.put(Self::default()).into() })
50                    })
51                    .build(),
52            )
53            .type_identifier("HashMap")
54            .type_params(&[
55                TypeParam {
56                    name: "K",
57                    shape: K::SHAPE,
58                },
59                TypeParam {
60                    name: "V",
61                    shape: V::SHAPE,
62                },
63            ])
64            .ty(Type::User(UserType::Opaque))
65            .def(Def::Map(
66                MapDef::builder()
67                    .k(K::SHAPE)
68                    .v(V::SHAPE)
69                    .vtable(
70                        &const {
71                            MapVTable::builder()
72                                .init_in_place_with_capacity(|uninit, capacity| unsafe {
73                                    uninit
74                                        .put(Self::with_capacity_and_hasher(capacity, S::default()))
75                                })
76                                .insert(|ptr, key, value| unsafe {
77                                    let map = ptr.as_mut::<HashMap<K, V>>();
78                                    let key = key.read::<K>();
79                                    let value = value.read::<V>();
80                                    map.insert(key, value);
81                                })
82                                .len(|ptr| unsafe {
83                                    let map = ptr.get::<HashMap<K, V>>();
84                                    map.len()
85                                })
86                                .contains_key(|ptr, key| unsafe {
87                                    let map = ptr.get::<HashMap<K, V>>();
88                                    map.contains_key(key.get())
89                                })
90                                .get_value_ptr(|ptr, key| unsafe {
91                                    let map = ptr.get::<HashMap<K, V>>();
92                                    map.get(key.get()).map(|v| PtrConst::new(NonNull::from(v)))
93                                })
94                                .iter_vtable(
95                                    IterVTable::builder()
96                                        .init_with_value(|ptr| unsafe {
97                                            let map = ptr.get::<HashMap<K, V>>();
98                                            let iter: HashMapIterator<'_, K, V> = map.iter();
99                                            let iter_state = Box::new(iter);
100                                            PtrMut::new(NonNull::new_unchecked(Box::into_raw(
101                                                iter_state,
102                                            )
103                                                as *mut u8))
104                                        })
105                                        .next(|iter_ptr| unsafe {
106                                            let state =
107                                                iter_ptr.as_mut::<HashMapIterator<'_, K, V>>();
108                                            state.next().map(|(key, value)| {
109                                                (
110                                                    PtrConst::new(NonNull::from(key)),
111                                                    PtrConst::new(NonNull::from(value)),
112                                                )
113                                            })
114                                        })
115                                        .dealloc(|iter_ptr| unsafe {
116                                            drop(Box::from_raw(
117                                                iter_ptr.as_ptr::<HashMapIterator<'_, K, V>>()
118                                                    as *mut HashMapIterator<'_, K, V>,
119                                            ));
120                                        })
121                                        .build(),
122                                )
123                                .build()
124                        },
125                    )
126                    .build(),
127            ))
128            .build()
129    };
130}
131
132unsafe impl Facet<'_> for RandomState {
133    const SHAPE: &'static Shape = &const {
134        Shape::builder_for_sized::<Self>()
135            .vtable(value_vtable!((), |f, _opts| write!(
136                f,
137                "{}",
138                Self::SHAPE.type_identifier
139            )))
140            .type_identifier("RandomState")
141            .ty(Type::User(UserType::Opaque))
142            .def(Def::Scalar)
143            .build()
144    };
145}