shapely_core/impls/
hashmap_impl.rs

1use std::{alloc::Layout, collections::HashMap, fmt};
2
3use crate::{Innards, NameOpts, Shape, Shapely, mini_typeid};
4
5impl<V> Shapely for HashMap<String, V>
6where
7    V: Shapely,
8{
9    fn shape() -> Shape {
10        // This name function doesn't need the type parameter
11        fn name<V: Shapely>(f: &mut fmt::Formatter, opts: NameOpts) -> fmt::Result {
12            if let Some(opts) = opts.for_children() {
13                write!(f, "HashMap<String, ")?;
14                (V::shape().name)(f, opts)?;
15                write!(f, ">")
16            } else {
17                write!(f, "HashMap<…>")
18            }
19        }
20
21        Shape {
22            name: name::<V> as _,
23            typeid: mini_typeid::of::<Self>(),
24            layout: Layout::new::<HashMap<String, V>>(),
25            innards: Innards::Map {
26                value_shape: V::shape_desc(),
27                vtable: crate::MapVTable {
28                    init: |ptr, size_hint| unsafe {
29                        let map = if let Some(capacity) = size_hint {
30                            HashMap::with_capacity(capacity)
31                        } else {
32                            HashMap::<String, V>::new()
33                        };
34                        std::ptr::write(ptr as *mut HashMap<String, V>, map);
35                    },
36                    insert: |ptr, key_partial, value_partial| unsafe {
37                        let map = &mut *(ptr as *mut HashMap<String, V>);
38                        let key = key_partial.build::<String>();
39                        let value = value_partial.build::<V>();
40                        map.insert(key, value);
41                    },
42                    len: |ptr| unsafe {
43                        let map = &*(ptr as *const HashMap<String, V>);
44                        map.len()
45                    },
46                    contains_key: |ptr, key| unsafe {
47                        let map = &*(ptr as *const HashMap<String, V>);
48                        map.contains_key(key)
49                    },
50                    get_value_ptr: |ptr, key| unsafe {
51                        let map = &*(ptr as *const HashMap<String, V>);
52                        if let Some(value) = map.get(key) {
53                            value as *const V as *const u8
54                        } else {
55                            std::ptr::null()
56                        }
57                    },
58                    iter: |ptr| unsafe {
59                        let map = &*(ptr as *const HashMap<String, V>);
60                        let entries: Vec<(String, *const V)> = map
61                            .iter()
62                            .map(|(k, v)| (k.clone(), v as *const V))
63                            .collect();
64
65                        let iter_state = Box::new((entries, 0usize));
66                        Box::into_raw(iter_state) as *const u8
67                    },
68                    iter_vtable: crate::MapIterVTable {
69                        next: |iter_ptr| unsafe {
70                            let state = &mut *(iter_ptr as *mut (Vec<(String, *const V)>, usize));
71                            let (entries, index) = state;
72
73                            if *index < entries.len() {
74                                let current = &entries[*index];
75                                let key_ptr = &current.0 as *const String;
76                                let value_ptr = current.1 as *const u8;
77                                *index += 1;
78                                Some((key_ptr, value_ptr))
79                            } else {
80                                None
81                            }
82                        },
83                        dealloc: |iter_ptr| unsafe {
84                            drop(Box::from_raw(
85                                iter_ptr as *mut (Vec<(String, *const V)>, usize),
86                            ));
87                        },
88                    },
89                },
90            },
91            set_to_default: Some(|addr: *mut u8| unsafe {
92                *(addr as *mut HashMap<String, V>) = HashMap::new();
93            }),
94            drop_in_place: Some(|addr: *mut u8| unsafe {
95                std::ptr::drop_in_place(addr as *mut HashMap<String, V>);
96            }),
97        }
98    }
99}