mica_language/value/
dicts.rs1use std::cell::UnsafeCell;
4use std::collections::hash_map::RandomState;
5use std::hash::{BuildHasher, Hash, Hasher};
6use std::mem;
7
8use hashbrown::raw::RawTable;
9
10use super::{RawValue, ValueKind};
11
12type DictMap = RawTable<(RawValue, RawValue)>;
13type DictHashBuilder = RandomState;
14
15#[derive(Default, Clone)]
16struct DictInner {
17 table: DictMap,
18 state: DictHashBuilder,
19}
20
21#[derive(Default)]
26pub struct Dict {
27 inner: UnsafeCell<DictInner>,
28}
29
30impl Dict {
31 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn len(&self) -> usize {
38 let inner = unsafe { &*self.inner.get() };
39 inner.table.len()
40 }
41
42 pub fn is_empty(&self) -> bool {
44 self.len() == 0
45 }
46
47 pub fn insert(&self, key: RawValue, value: RawValue) -> RawValue {
49 let inner = unsafe { &mut *self.inner.get() };
50 let hasher = make_hasher(&inner.state);
51 let key_hash = hasher(&(key, value));
52 if let Some((_, item)) = inner.table.get_mut(key_hash, equivalent_key(key)) {
53 mem::replace(item, value)
54 } else {
55 inner.table.insert(key_hash, (key, value), hasher);
56 RawValue::from(())
57 }
58 }
59
60 pub fn remove(&self, key: RawValue) -> RawValue {
62 let inner = unsafe { &mut *self.inner.get() };
63 match inner.table.remove_entry(
64 key.hash(&mut inner.state.build_hasher()),
65 equivalent_key(key),
66 ) {
67 Some((_, v)) => v,
68 None => RawValue::from(()),
69 }
70 }
71
72 pub fn get(&self, key: RawValue) -> Option<RawValue> {
74 let inner = unsafe { &*self.inner.get() };
75 if inner.table.is_empty() {
76 None
77 } else {
78 let hash = key.hash(&mut inner.state.build_hasher());
79 inner.table.get(hash, equivalent_key(key)).map(|&(_key, value)| value)
80 }
81 }
82
83 pub fn contains_key(&self, key: RawValue) -> bool {
85 self.get(key).is_some()
86 }
87
88 pub(crate) unsafe fn iter(&self) -> impl Iterator<Item = (RawValue, RawValue)> + '_ {
94 let inner = &*self.inner.get();
95 let iterator = inner.table.iter();
96 iterator.map(|bucket| bucket.read())
97 }
98}
99
100impl Clone for Dict {
101 fn clone(&self) -> Self {
102 Self {
103 inner: UnsafeCell::new((unsafe { &*self.inner.get() }).clone()),
104 }
105 }
106}
107
108impl PartialEq for Dict {
109 fn eq(&self, other: &Self) -> bool {
110 if self.len() != other.len() {
111 return false;
112 }
113 unsafe { self.iter() }.all(|(key, value)| other.get(key).map_or(false, |v| value == v))
114 }
115}
116
117impl RawValue {
118 pub fn hash<H>(&self, state: &mut H) -> u64
122 where
123 H: Hasher,
124 {
125 self.kind().hash(state);
126 unsafe {
127 match self.kind() {
128 ValueKind::Nil => (),
130 ValueKind::Boolean => self.get_boolean_unchecked().hash(state),
131 ValueKind::Number => self.get_number_unchecked().to_bits().hash(state),
134 ValueKind::String => self.get_raw_string_unchecked().get().hash(state),
135 ValueKind::Function => self.get_raw_function_unchecked().get_raw().hash(state),
137 ValueKind::Struct => self.get_raw_struct_unchecked().get_raw().hash(state),
138 ValueKind::Trait => self.get_raw_trait_unchecked().get_raw().hash(state),
139 ValueKind::List => {
140 let slice = self.get_raw_list_unchecked().get().as_slice();
141 slice.len().hash(state);
142 for value in slice.iter() {
143 value.hash(state);
144 }
145 }
146 ValueKind::Dict => {
147 let dict = self.get_raw_dict_unchecked().get();
151 for (key, value) in dict.iter() {
152 key.hash(state);
153 value.hash(state);
154 }
155 }
156 ValueKind::UserData => self.get_raw_user_data_unchecked().get_raw().hash(state),
157 }
158 }
159 state.finish()
160 }
161}
162
163fn make_hasher(builder: &DictHashBuilder) -> impl Fn(&(RawValue, RawValue)) -> u64 + '_ {
164 move |&(key, _value)| key.hash(&mut builder.build_hasher())
165}
166
167fn equivalent_key(key: RawValue) -> impl Fn(&(RawValue, RawValue)) -> bool {
168 move |&(key2, _value)| key == key2
169}