1use std::borrow::Borrow;
9use std::ptr;
10
11use kevy_hash::KevyHash;
12
13use crate::group::Group;
14use crate::map::{DELETED, EMPTY, GROUP_WIDTH, KevyMap, MIN_CAP, ProbeOutcome, h2};
15
16impl<K: KevyHash + Eq, V> KevyMap<K, V> {
17 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
21 self.maybe_grow();
22 let hash = key.kevy_hash();
23 match self.probe_with_key(hash, &key) {
24 ProbeOutcome::Found(idx) => {
25 let v_ptr = unsafe {
28 let kv: *mut (K, V) = self.slots_ptr.as_ptr().add(idx).cast::<(K, V)>();
29 ptr::addr_of_mut!((*kv).1)
30 };
31 let old_v = unsafe { ptr::replace(v_ptr, value) };
32 drop(key);
33 Some(old_v)
34 }
35 ProbeOutcome::NotFound {
36 insert_at,
37 via_tombstone,
38 } => {
39 self.set_meta(insert_at, h2(hash));
40 unsafe {
43 (*self.slots_ptr.as_ptr().add(insert_at)).write((key, value));
44 }
45 self.occupied += 1;
46 if via_tombstone {
47 self.deleted -= 1;
48 }
49 None
50 }
51 }
52 }
53
54 pub(crate) fn maybe_grow(&mut self) {
55 if self.cap == 0 || (self.occupied + self.deleted) >= self.threshold() {
56 self.grow();
57 }
58 }
59
60 fn grow(&mut self) {
61 let new_cap = if self.cap == 0 {
62 MIN_CAP
63 } else {
64 self.cap
65 .checked_mul(2)
66 .expect("kevy-map: capacity doubling overflow")
67 };
68 let mut new_table = Self::alloc_table(new_cap);
69 let old_cap = self.cap;
79 for i in 0..old_cap {
80 let meta = unsafe { *self.metadata_ptr.as_ptr().add(i) };
82 if meta & 0x80 == 0 {
83 let (k, v) = unsafe { ptr::read(self.slots_ptr.as_ptr().add(i) as *const (K, V)) };
86 unsafe { *self.metadata_ptr.as_ptr().add(i) = DELETED };
87 let hash = k.kevy_hash();
88 new_table.insert_known_unique(hash, k, v);
89 }
90 }
91 self.occupied = 0;
93 self.deleted = 0;
94 std::mem::swap(self, &mut new_table);
95 }
98
99 fn insert_known_unique(&mut self, hash: u64, k: K, v: V) {
103 let h2v = h2(hash);
104 let mut group_start = (hash as usize) & self.mask;
105 loop {
106 let g = unsafe { Group::load(self.metadata_ptr.as_ptr().add(group_start)) };
110 if let Some(m) = g.match_byte(EMPTY).lowest_set() {
111 let slot = (group_start + m) & self.mask;
112 self.set_meta(slot, h2v);
113 unsafe {
115 (*self.slots_ptr.as_ptr().add(slot)).write((k, v));
116 }
117 self.occupied += 1;
118 return;
119 }
120 group_start = (group_start + GROUP_WIDTH) & self.mask;
125 }
126 }
127
128 fn probe_with_key(&self, hash: u64, key: &K) -> ProbeOutcome {
130 if self.cap == 0 {
131 return ProbeOutcome::NotFound {
132 insert_at: 0,
133 via_tombstone: false,
134 };
135 }
136 let h2v = h2(hash);
137 let mut group_start = (hash as usize) & self.mask;
138
139 if self.deleted == 0 {
144 loop {
145 let g = unsafe { Group::load(self.metadata_ptr.as_ptr().add(group_start)) };
147 for m in g.match_byte(h2v).iter() {
148 let slot = (group_start + m) & self.mask;
149 let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_ref() };
151 if &kv.0 == key {
152 return ProbeOutcome::Found(slot);
153 }
154 }
155 if let Some(m) = g.match_byte(EMPTY).lowest_set() {
156 return ProbeOutcome::NotFound {
157 insert_at: (group_start + m) & self.mask,
158 via_tombstone: false,
159 };
160 }
161 group_start = (group_start + GROUP_WIDTH) & self.mask;
162 }
163 }
164
165 let mut first_deleted: Option<usize> = None;
168 loop {
169 let g = unsafe { Group::load(self.metadata_ptr.as_ptr().add(group_start)) };
171 for m in g.match_byte(h2v).iter() {
172 let slot = (group_start + m) & self.mask;
173 let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_ref() };
175 if &kv.0 == key {
176 return ProbeOutcome::Found(slot);
177 }
178 }
179 if first_deleted.is_none()
180 && let Some(m) = g.match_byte(DELETED).lowest_set()
181 {
182 first_deleted = Some((group_start + m) & self.mask);
183 }
184 if let Some(m) = g.match_byte(EMPTY).lowest_set() {
185 let probe_empty = (group_start + m) & self.mask;
186 return ProbeOutcome::NotFound {
187 insert_at: first_deleted.unwrap_or(probe_empty),
188 via_tombstone: first_deleted.is_some(),
189 };
190 }
191 group_start = (group_start + GROUP_WIDTH) & self.mask;
192 }
193 }
194}
195
196impl<K, V> KevyMap<K, V> {
197 pub fn get<Q>(&self, key: &Q) -> Option<&V>
199 where
200 K: Borrow<Q>,
201 Q: KevyHash + Eq + ?Sized,
202 {
203 let idx = self.find_by_borrow(key)?;
204 let kv = unsafe { (*self.slots_ptr.as_ptr().add(idx)).assume_init_ref() };
206 Some(&kv.1)
207 }
208
209 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
211 where
212 K: Borrow<Q>,
213 Q: KevyHash + Eq + ?Sized,
214 {
215 let idx = self.find_by_borrow(key)?;
216 let kv = unsafe { (*self.slots_ptr.as_ptr().add(idx)).assume_init_mut() };
218 Some(&mut kv.1)
219 }
220
221 pub fn contains_key<Q>(&self, key: &Q) -> bool
223 where
224 K: Borrow<Q>,
225 Q: KevyHash + Eq + ?Sized,
226 {
227 self.find_by_borrow(key).is_some()
228 }
229
230 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
232 where
233 K: Borrow<Q>,
234 Q: KevyHash + Eq + ?Sized,
235 {
236 let idx = self.find_by_borrow(key)?;
237 self.set_meta(idx, DELETED);
238 self.occupied -= 1;
239 self.deleted += 1;
240 let (_k, v) = unsafe { ptr::read(self.slots_ptr.as_ptr().add(idx) as *const (K, V)) };
243 Some(v)
244 }
245
246 pub(crate) fn find_by_borrow<Q>(&self, key: &Q) -> Option<usize>
247 where
248 K: Borrow<Q>,
249 Q: KevyHash + Eq + ?Sized,
250 {
251 if self.cap == 0 {
252 return None;
253 }
254 let hash = key.kevy_hash();
255 let h2v = h2(hash);
256 let mut group_start = (hash as usize) & self.mask;
257 loop {
258 let g = unsafe { Group::load(self.metadata_ptr.as_ptr().add(group_start)) };
261 for m in g.match_byte(h2v).iter() {
262 let slot = (group_start + m) & self.mask;
263 let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_ref() };
265 if kv.0.borrow() == key {
266 return Some(slot);
267 }
268 }
269 if !g.match_byte(EMPTY).is_empty() {
271 return None;
272 }
273 group_start = (group_start + GROUP_WIDTH) & self.mask;
274 }
275 }
276
277 pub(crate) fn probe_by_borrow<Q>(&self, key: &Q) -> ProbeOutcome
285 where
286 K: Borrow<Q>,
287 Q: KevyHash + Eq + ?Sized,
288 {
289 if self.cap == 0 {
290 return ProbeOutcome::NotFound {
291 insert_at: 0,
292 via_tombstone: false,
293 };
294 }
295 let hash = key.kevy_hash();
296 let h2v = h2(hash);
297 let group_start = (hash as usize) & self.mask;
298 if self.deleted == 0 {
299 self.probe_by_borrow_fast(key, h2v, group_start)
300 } else {
301 self.probe_by_borrow_slow(key, h2v, group_start)
302 }
303 }
304
305 fn probe_by_borrow_fast<Q>(&self, key: &Q, h2v: u8, mut group_start: usize) -> ProbeOutcome
308 where
309 K: Borrow<Q>,
310 Q: KevyHash + Eq + ?Sized,
311 {
312 loop {
313 let g = unsafe { Group::load(self.metadata_ptr.as_ptr().add(group_start)) };
315 for m in g.match_byte(h2v).iter() {
316 let slot = (group_start + m) & self.mask;
317 let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_ref() };
319 if kv.0.borrow() == key {
320 return ProbeOutcome::Found(slot);
321 }
322 }
323 if let Some(m) = g.match_byte(EMPTY).lowest_set() {
324 return ProbeOutcome::NotFound {
325 insert_at: (group_start + m) & self.mask,
326 via_tombstone: false,
327 };
328 }
329 group_start = (group_start + GROUP_WIDTH) & self.mask;
330 }
331 }
332
333 fn probe_by_borrow_slow<Q>(&self, key: &Q, h2v: u8, mut group_start: usize) -> ProbeOutcome
336 where
337 K: Borrow<Q>,
338 Q: KevyHash + Eq + ?Sized,
339 {
340 let mut first_deleted: Option<usize> = None;
341 loop {
342 let g = unsafe { Group::load(self.metadata_ptr.as_ptr().add(group_start)) };
344 for m in g.match_byte(h2v).iter() {
345 let slot = (group_start + m) & self.mask;
346 let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_ref() };
348 if kv.0.borrow() == key {
349 return ProbeOutcome::Found(slot);
350 }
351 }
352 if first_deleted.is_none()
353 && let Some(m) = g.match_byte(DELETED).lowest_set()
354 {
355 first_deleted = Some((group_start + m) & self.mask);
356 }
357 if let Some(m) = g.match_byte(EMPTY).lowest_set() {
358 let probe_empty = (group_start + m) & self.mask;
359 return ProbeOutcome::NotFound {
360 insert_at: first_deleted.unwrap_or(probe_empty),
361 via_tombstone: first_deleted.is_some(),
362 };
363 }
364 group_start = (group_start + GROUP_WIDTH) & self.mask;
365 }
366 }
367}