shapely_core/impls/
hashmap_impl.rs1use 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 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 = ¤t.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}