1mod entry;
11mod extract;
12
13use alloc::vec::{self, Vec};
14use core::mem;
15use core::ops::RangeBounds;
16use hashbrown::hash_table;
17
18use crate::util::{assert_index_le, assert_index_lt, simplify_range};
19use crate::{Bucket, Equivalent, HashValue, TryReserveError};
20
21type Indices = hash_table::HashTable<usize>;
22type Entries<K, V> = Vec<Bucket<K, V>>;
23
24pub use entry::{OccupiedEntry, VacantEntry};
25pub(crate) use extract::ExtractCore;
26
27#[cfg_attr(feature = "test_debug", derive(Debug))]
29pub(crate) struct Core<K, V> {
30 indices: Indices,
32 entries: Entries<K, V>,
34}
35
36#[inline(always)]
37fn get_hash<K, V>(entries: &[Bucket<K, V>]) -> impl Fn(&usize) -> u64 + use<'_, K, V> {
38 move |&i| entries[i].hash.get()
39}
40
41#[inline]
42fn equal<'a, K: Eq, V>(
43 key: &'a K,
44 entries: &'a [Bucket<K, V>],
45) -> impl Fn(&usize) -> bool + use<'a, K, V> {
46 move |&i| K::eq(key, &entries[i].key)
47}
48
49#[inline]
50fn equivalent<'a, K, V, Q: ?Sized + Equivalent<K>>(
51 key: &'a Q,
52 entries: &'a [Bucket<K, V>],
53) -> impl Fn(&usize) -> bool + use<'a, K, V, Q> {
54 move |&i| Q::equivalent(key, &entries[i].key)
55}
56
57#[inline]
58fn erase_index(table: &mut Indices, hash: HashValue, index: usize) {
59 if let Ok(entry) = table.find_entry(hash.get(), move |&i| i == index) {
60 entry.remove();
61 } else if cfg!(debug_assertions) {
62 panic!("index not found");
63 }
64}
65
66#[inline]
67fn update_index(table: &mut Indices, hash: HashValue, old: usize, new: usize) {
68 let index = table
69 .find_mut(hash.get(), move |&i| i == old)
70 .expect("index not found");
71 *index = new;
72}
73
74fn insert_bulk_no_grow<K, V>(indices: &mut Indices, entries: &[Bucket<K, V>]) {
79 assert!(indices.capacity() - indices.len() >= entries.len());
80 for entry in entries {
81 indices.insert_unique(entry.hash.get(), indices.len(), |_| unreachable!());
82 }
83}
84
85impl<K, V> Clone for Core<K, V>
86where
87 K: Clone,
88 V: Clone,
89{
90 fn clone(&self) -> Self {
91 let mut new = Self::new();
92 new.clone_from(self);
93 new
94 }
95
96 fn clone_from(&mut self, other: &Self) {
97 self.indices.clone_from(&other.indices);
98 if self.entries.capacity() < other.entries.len() {
99 let additional = other.entries.len() - self.entries.len();
101 self.reserve_entries(additional);
102 }
103 self.entries.clone_from(&other.entries);
104 }
105}
106
107impl<K, V> Core<K, V> {
108 const MAX_ENTRIES_CAPACITY: usize = (isize::MAX as usize) / size_of::<Bucket<K, V>>();
110
111 #[inline]
112 pub(crate) const fn new() -> Self {
113 Core {
114 indices: Indices::new(),
115 entries: Vec::new(),
116 }
117 }
118
119 #[inline]
120 pub(crate) fn with_capacity(n: usize) -> Self {
121 Core {
122 indices: Indices::with_capacity(n),
123 entries: Vec::with_capacity(n),
124 }
125 }
126
127 #[inline]
128 pub(crate) fn into_entries(self) -> Entries<K, V> {
129 self.entries
130 }
131
132 #[inline]
133 pub(crate) fn as_entries(&self) -> &[Bucket<K, V>] {
134 &self.entries
135 }
136
137 #[inline]
138 pub(crate) fn as_entries_mut(&mut self) -> &mut [Bucket<K, V>] {
139 &mut self.entries
140 }
141
142 pub(crate) fn with_entries<F>(&mut self, f: F)
143 where
144 F: FnOnce(&mut [Bucket<K, V>]),
145 {
146 f(&mut self.entries);
147 self.rebuild_hash_table();
148 }
149
150 #[inline]
151 pub(crate) fn len(&self) -> usize {
152 debug_assert_eq!(self.entries.len(), self.indices.len());
153 self.indices.len()
154 }
155
156 #[inline]
157 pub(crate) fn capacity(&self) -> usize {
158 Ord::min(self.indices.capacity(), self.entries.capacity())
159 }
160
161 pub(crate) fn clear(&mut self) {
162 self.indices.clear();
163 self.entries.clear();
164 }
165
166 pub(crate) fn truncate(&mut self, len: usize) {
167 if len < self.len() {
168 self.erase_indices(len, self.entries.len());
169 self.entries.truncate(len);
170 }
171 }
172
173 #[track_caller]
174 pub(crate) fn drain<R>(&mut self, range: R) -> vec::Drain<'_, Bucket<K, V>>
175 where
176 R: RangeBounds<usize>,
177 {
178 let range = simplify_range(range, self.entries.len());
179 self.erase_indices(range.start, range.end);
180 self.entries.drain(range)
181 }
182
183 #[cfg(feature = "rayon")]
184 pub(crate) fn par_drain<R>(&mut self, range: R) -> rayon::vec::Drain<'_, Bucket<K, V>>
185 where
186 K: Send,
187 V: Send,
188 R: RangeBounds<usize>,
189 {
190 use rayon::iter::ParallelDrainRange;
191 let range = simplify_range(range, self.entries.len());
192 self.erase_indices(range.start, range.end);
193 self.entries.par_drain(range)
194 }
195
196 #[track_caller]
197 pub(crate) fn split_off(&mut self, at: usize) -> Self {
198 assert_index_le(at, self.len());
199
200 self.erase_indices(at, self.entries.len());
201 let entries = self.entries.split_off(at);
202
203 let mut indices = Indices::with_capacity(entries.len());
204 insert_bulk_no_grow(&mut indices, &entries);
205 Self { indices, entries }
206 }
207
208 #[track_caller]
209 pub(crate) fn split_splice<R>(&mut self, range: R) -> (Self, vec::IntoIter<Bucket<K, V>>)
210 where
211 R: RangeBounds<usize>,
212 {
213 let range = simplify_range(range, self.len());
214 self.erase_indices(range.start, self.entries.len());
215 let entries = self.entries.split_off(range.end);
216 let drained = self.entries.split_off(range.start);
217
218 let mut indices = Indices::with_capacity(entries.len());
219 insert_bulk_no_grow(&mut indices, &entries);
220 (Self { indices, entries }, drained.into_iter())
221 }
222
223 pub(crate) fn append_unchecked(&mut self, other: &mut Self) {
225 self.reserve(other.len());
226 insert_bulk_no_grow(&mut self.indices, &other.entries);
227 self.entries.append(&mut other.entries);
228 other.indices.clear();
229 }
230
231 pub(crate) fn reserve(&mut self, additional: usize) {
233 self.indices.reserve(additional, get_hash(&self.entries));
234 if additional > self.entries.capacity() - self.entries.len() {
236 self.reserve_entries(additional);
237 }
238 }
239
240 pub(crate) fn reserve_exact(&mut self, additional: usize) {
242 self.indices.reserve(additional, get_hash(&self.entries));
243 self.entries.reserve_exact(additional);
244 }
245
246 pub(crate) fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
248 self.indices
249 .try_reserve(additional, get_hash(&self.entries))
250 .map_err(TryReserveError::from_hashbrown)?;
251 if additional > self.entries.capacity() - self.entries.len() {
253 self.try_reserve_entries(additional)
254 } else {
255 Ok(())
256 }
257 }
258
259 fn try_reserve_entries(&mut self, additional: usize) -> Result<(), TryReserveError> {
261 let new_capacity = Ord::min(self.indices.capacity(), Self::MAX_ENTRIES_CAPACITY);
264 let try_add = new_capacity - self.entries.len();
265 if try_add > additional && self.entries.try_reserve_exact(try_add).is_ok() {
266 return Ok(());
267 }
268 self.entries
269 .try_reserve_exact(additional)
270 .map_err(TryReserveError::from_alloc)
271 }
272
273 pub(crate) fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
275 self.indices
276 .try_reserve(additional, get_hash(&self.entries))
277 .map_err(TryReserveError::from_hashbrown)?;
278 self.entries
279 .try_reserve_exact(additional)
280 .map_err(TryReserveError::from_alloc)
281 }
282
283 pub(crate) fn shrink_to(&mut self, min_capacity: usize) {
285 self.indices
286 .shrink_to(min_capacity, get_hash(&self.entries));
287 self.entries.shrink_to(min_capacity);
288 }
289
290 pub(crate) fn pop(&mut self) -> Option<(K, V)> {
292 if let Some(entry) = self.entries.pop() {
293 let last = self.entries.len();
294 erase_index(&mut self.indices, entry.hash, last);
295 Some((entry.key, entry.value))
296 } else {
297 None
298 }
299 }
300
301 pub(crate) fn get_index_of<Q>(&self, hash: HashValue, key: &Q) -> Option<usize>
303 where
304 Q: ?Sized + Equivalent<K>,
305 {
306 let eq = equivalent(key, &self.entries);
307 self.indices.find(hash.get(), eq).copied()
308 }
309
310 pub(crate) fn get_index_of_raw<F>(&self, hash: HashValue, mut is_match: F) -> Option<usize>
312 where
313 F: FnMut(&K) -> bool,
314 {
315 let eq = move |&i: &usize| is_match(&self.entries[i].key);
316 self.indices.find(hash.get(), eq).copied()
317 }
318
319 fn push_entry(&mut self, hash: HashValue, key: K, value: V) {
322 if self.entries.len() == self.entries.capacity() {
323 self.reserve_entries(1);
326 }
327 self.entries.push(Bucket { hash, key, value });
328 }
329
330 pub(crate) fn insert_full(&mut self, hash: HashValue, key: K, value: V) -> (usize, Option<V>)
331 where
332 K: Eq,
333 {
334 let eq = equal(&key, &self.entries);
335 let hasher = get_hash(&self.entries);
336 match self.indices.entry(hash.get(), eq, hasher) {
337 hash_table::Entry::Occupied(entry) => {
338 let i = *entry.get();
339 (i, Some(mem::replace(&mut self.entries[i].value, value)))
340 }
341 hash_table::Entry::Vacant(entry) => {
342 let i = self.entries.len();
343 entry.insert(i);
344 self.push_entry(hash, key, value);
345 debug_assert_eq!(self.indices.len(), self.entries.len());
346 (i, None)
347 }
348 }
349 }
350
351 pub(crate) fn replace_full(
353 &mut self,
354 hash: HashValue,
355 key: K,
356 value: V,
357 ) -> (usize, Option<(K, V)>)
358 where
359 K: Eq,
360 {
361 let eq = equal(&key, &self.entries);
362 let hasher = get_hash(&self.entries);
363 match self.indices.entry(hash.get(), eq, hasher) {
364 hash_table::Entry::Occupied(entry) => {
365 let i = *entry.get();
366 let entry = &mut self.entries[i];
367 let kv = (
368 mem::replace(&mut entry.key, key),
369 mem::replace(&mut entry.value, value),
370 );
371 (i, Some(kv))
372 }
373 hash_table::Entry::Vacant(entry) => {
374 let i = self.entries.len();
375 entry.insert(i);
376 self.push_entry(hash, key, value);
377 debug_assert_eq!(self.indices.len(), self.entries.len());
378 (i, None)
379 }
380 }
381 }
382
383 pub(crate) fn shift_remove_full<Q>(&mut self, hash: HashValue, key: &Q) -> Option<(usize, K, V)>
385 where
386 Q: ?Sized + Equivalent<K>,
387 {
388 let eq = equivalent(key, &self.entries);
389 let (index, _) = self.indices.find_entry(hash.get(), eq).ok()?.remove();
390 let (key, value) = self.shift_remove_finish(index);
391 Some((index, key, value))
392 }
393
394 pub(crate) fn swap_remove_full<Q>(&mut self, hash: HashValue, key: &Q) -> Option<(usize, K, V)>
396 where
397 Q: ?Sized + Equivalent<K>,
398 {
399 let eq = equivalent(key, &self.entries);
400 let (index, _) = self.indices.find_entry(hash.get(), eq).ok()?.remove();
401 let (key, value) = self.swap_remove_finish(index);
402 Some((index, key, value))
403 }
404
405 fn erase_indices(&mut self, start: usize, end: usize) {
410 let (init, shifted_entries) = self.entries.split_at(end);
411 let (start_entries, erased_entries) = init.split_at(start);
412
413 let erased = erased_entries.len();
414 let shifted = shifted_entries.len();
415 let half_capacity = self.indices.capacity() / 2;
416
417 if erased == 0 {
419 } else if start + shifted < half_capacity && start < erased {
421 self.indices.clear();
423
424 insert_bulk_no_grow(&mut self.indices, start_entries);
426 insert_bulk_no_grow(&mut self.indices, shifted_entries);
427 } else if erased + shifted < half_capacity {
428 for (i, entry) in (start..).zip(erased_entries) {
432 erase_index(&mut self.indices, entry.hash, i);
433 }
434
435 for ((new, old), entry) in (start..).zip(end..).zip(shifted_entries) {
437 update_index(&mut self.indices, entry.hash, old, new);
438 }
439 } else {
440 let offset = end - start;
442 self.indices.retain(move |i| {
443 if *i >= end {
444 *i -= offset;
445 true
446 } else {
447 *i < start
448 }
449 });
450 }
451
452 debug_assert_eq!(self.indices.len(), start + shifted);
453 }
454
455 pub(crate) fn retain_in_order<F>(&mut self, mut keep: F)
456 where
457 F: FnMut(&mut K, &mut V) -> bool,
458 {
459 self.entries
460 .retain_mut(|entry| keep(&mut entry.key, &mut entry.value));
461 if self.entries.len() < self.indices.len() {
462 self.rebuild_hash_table();
463 }
464 }
465
466 fn rebuild_hash_table(&mut self) {
467 self.indices.clear();
468 insert_bulk_no_grow(&mut self.indices, &self.entries);
469 }
470
471 pub(crate) fn reverse(&mut self) {
472 self.entries.reverse();
473
474 let len = self.entries.len();
477 for i in &mut self.indices {
478 *i = len - *i - 1;
479 }
480 }
481
482 #[inline]
484 fn reserve_entries(&mut self, additional: usize) {
485 let try_capacity = Ord::min(self.indices.capacity(), Self::MAX_ENTRIES_CAPACITY);
488 let try_add = try_capacity - self.entries.len();
489 if try_add > additional && self.entries.try_reserve_exact(try_add).is_ok() {
490 return;
491 }
492 self.entries.reserve_exact(additional);
493 }
494
495 pub(super) fn insert_unique(&mut self, hash: HashValue, key: K, value: V) -> &mut Bucket<K, V> {
498 let i = self.indices.len();
499 debug_assert_eq!(i, self.entries.len());
500 self.indices
501 .insert_unique(hash.get(), i, get_hash(&self.entries));
502 self.push_entry(hash, key, value);
503 &mut self.entries[i]
504 }
505
506 #[track_caller]
509 pub(crate) fn replace_index_unique(&mut self, index: usize, hash: HashValue, key: K) -> K {
510 erase_index(&mut self.indices, self.entries[index].hash, index);
513 self.indices
514 .insert_unique(hash.get(), index, get_hash(&self.entries));
515
516 let entry = &mut self.entries[index];
517 entry.hash = hash;
518 mem::replace(&mut entry.key, key)
519 }
520
521 pub(crate) fn shift_insert_unique(
524 &mut self,
525 index: usize,
526 hash: HashValue,
527 key: K,
528 value: V,
529 ) -> &mut Bucket<K, V> {
530 let end = self.indices.len();
531 assert!(index <= end);
532 self.increment_indices(index, end);
534 let entries = &*self.entries;
535 self.indices.insert_unique(hash.get(), index, move |&i| {
536 debug_assert_ne!(i, index);
538 let i = if i < index { i } else { i - 1 };
539 entries[i].hash.get()
540 });
541 if self.entries.len() == self.entries.capacity() {
542 self.reserve_entries(1);
545 }
546 self.entries.insert(index, Bucket { hash, key, value });
547 &mut self.entries[index]
548 }
549
550 pub(crate) fn shift_remove_index(&mut self, index: usize) -> Option<(K, V)> {
552 match self.entries.get(index) {
553 Some(entry) => {
554 erase_index(&mut self.indices, entry.hash, index);
555 Some(self.shift_remove_finish(index))
556 }
557 None => None,
558 }
559 }
560
561 fn shift_remove_finish(&mut self, index: usize) -> (K, V) {
565 self.decrement_indices(index + 1, self.entries.len());
567
568 let entry = self.entries.remove(index);
570 (entry.key, entry.value)
571 }
572
573 pub(crate) fn swap_remove_index(&mut self, index: usize) -> Option<(K, V)> {
575 match self.entries.get(index) {
576 Some(entry) => {
577 erase_index(&mut self.indices, entry.hash, index);
578 Some(self.swap_remove_finish(index))
579 }
580 None => None,
581 }
582 }
583
584 fn swap_remove_finish(&mut self, index: usize) -> (K, V) {
588 let entry = self.entries.swap_remove(index);
591
592 if let Some(entry) = self.entries.get(index) {
594 let last = self.entries.len();
597 update_index(&mut self.indices, entry.hash, last, index);
598 }
599
600 (entry.key, entry.value)
601 }
602
603 fn decrement_indices(&mut self, start: usize, end: usize) {
608 let shifted_entries = &self.entries[start..end];
610 if shifted_entries.len() > self.indices.capacity() / 2 {
611 for i in &mut self.indices {
613 if start <= *i && *i < end {
614 *i -= 1;
615 }
616 }
617 } else {
618 for (i, entry) in (start..end).zip(shifted_entries) {
620 update_index(&mut self.indices, entry.hash, i, i - 1);
621 }
622 }
623 }
624
625 fn increment_indices(&mut self, start: usize, end: usize) {
630 let shifted_entries = &self.entries[start..end];
632 if shifted_entries.len() > self.indices.capacity() / 2 {
633 for i in &mut self.indices {
635 if start <= *i && *i < end {
636 *i += 1;
637 }
638 }
639 } else {
640 for (i, entry) in (start..end).zip(shifted_entries).rev() {
643 update_index(&mut self.indices, entry.hash, i, i + 1);
644 }
645 }
646 }
647
648 #[track_caller]
649 pub(super) fn move_index(&mut self, from: usize, to: usize) {
650 assert_index_lt(from, self.len());
651 let from_hash = self.entries[from].hash;
652 if from != to {
653 assert_index_lt(to, self.len());
654
655 let bucket = self
657 .indices
658 .find_bucket_index(from_hash.get(), move |&i| i == from)
659 .expect("index not found");
660
661 self.move_index_inner(from, to);
662 *self.indices.get_bucket_mut(bucket).unwrap() = to;
663 }
664 }
665
666 fn move_index_inner(&mut self, from: usize, to: usize) {
667 if from < to {
669 self.decrement_indices(from + 1, to + 1);
670 self.entries[from..=to].rotate_left(1);
671 } else if to < from {
672 self.increment_indices(to, from);
673 self.entries[to..=from].rotate_right(1);
674 }
675 }
676
677 #[track_caller]
678 pub(crate) fn swap_indices(&mut self, a: usize, b: usize) {
679 assert_index_lt(a, self.len());
680 if a == b {
681 return;
683 }
684 assert_index_lt(b, self.len());
685
686 match self.indices.get_disjoint_mut(
688 [self.entries[a].hash.get(), self.entries[b].hash.get()],
689 move |i, &x| if i == 0 { x == a } else { x == b },
690 ) {
691 [Some(ref_a), Some(ref_b)] => {
692 mem::swap(ref_a, ref_b);
693 self.entries.swap(a, b);
694 }
695 _ => panic!("indices not found"),
696 }
697 }
698}
699
700#[test]
701fn assert_send_sync() {
702 fn assert_send_sync<T: Send + Sync>() {}
703 assert_send_sync::<Core<i32, i32>>();
704}