Skip to main content

radixdb_core/
i64_map.rs

1// Copyright 2026 RadixDB Contributors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! High-performance i64 map and set shared by lower-level RadixDB crates.
16// - Uses i64::MIN as the in-table empty sentinel and stores that one key out of band
17// - Direct key storage (no XOR transform)
18// - FxHash with pre-mixing (XOR>>16 before multiply) - 0 sequential collisions,
19//   65% reduction in strided key collisions
20// - Backward-shift deletion (no tombstones)
21//
22use std::mem::MaybeUninit;
23
24const MIN_CAPACITY: usize = 8;
25const LOAD_FACTOR_NUM: usize = 3;
26const LOAD_FACTOR_DEN: usize = 4;
27
28/// Shrink threshold: shrink when len < capacity / SHRINK_DIVISOR
29/// Only shrink if capacity > MIN_SHRINK_CAPACITY to avoid thrashing
30const SHRINK_DIVISOR: usize = 4;
31const MIN_SHRINK_CAPACITY: usize = 64;
32
33// Empty in-table sentinel. The same logical key is stored out of band.
34const EMPTY: i64 = i64::MIN;
35
36/// Slot with key and value. key == EMPTY means slot is empty.
37#[repr(C)]
38struct Slot<V> {
39    key: i64,
40    value: MaybeUninit<V>,
41}
42
43/// High-performance HashMap for i64 keys.
44/// Supports the full `i64` key domain. `i64::MIN` is stored out of band so the
45/// hot open-addressed table can continue using it as its empty-slot sentinel.
46pub struct I64Map<V> {
47    slots: Box<[Slot<V>]>,
48    min_value: Option<V>,
49    len: usize,
50    mask: usize,
51}
52
53impl<V: Clone> Clone for I64Map<V> {
54    fn clone(&self) -> Self {
55        let mut new_map = Self::with_capacity(self.len);
56        for (key, value) in self.iter() {
57            new_map.insert(key, value.clone());
58        }
59        new_map
60    }
61}
62
63impl<V> Default for I64Map<V> {
64    #[inline(always)]
65    fn default() -> Self {
66        Self::new()
67    }
68}
69
70impl<V> I64Map<V> {
71    #[inline(always)]
72    pub fn new() -> Self {
73        Self::with_capacity(0)
74    }
75
76    pub fn with_capacity(capacity: usize) -> Self {
77        let cap = if capacity == 0 {
78            MIN_CAPACITY
79        } else {
80            capacity
81                .saturating_mul(LOAD_FACTOR_DEN)
82                .saturating_div(LOAD_FACTOR_NUM)
83                .next_power_of_two()
84                .max(MIN_CAPACITY)
85        };
86
87        let slots: Vec<Slot<V>> = (0..cap)
88            .map(|_| Slot {
89                key: EMPTY,
90                value: MaybeUninit::uninit(),
91            })
92            .collect();
93
94        Self {
95            slots: slots.into_boxed_slice(),
96            min_value: None,
97            len: 0,
98            mask: cap - 1,
99        }
100    }
101
102    #[inline(always)]
103    pub fn len(&self) -> usize {
104        self.len
105    }
106
107    #[inline(always)]
108    pub fn is_empty(&self) -> bool {
109        self.len == 0
110    }
111
112    #[inline(always)]
113    pub fn capacity(&self) -> usize {
114        self.slots.len()
115    }
116
117    /// Reserves capacity for at least `additional` more elements to be inserted
118    /// in the map. The collection may reserve more space to avoid frequent reallocations.
119    pub fn reserve(&mut self, additional: usize) {
120        let target_len = self.len + additional;
121        let target_cap = if target_len == 0 {
122            MIN_CAPACITY
123        } else {
124            target_len
125                .saturating_mul(LOAD_FACTOR_DEN)
126                .saturating_div(LOAD_FACTOR_NUM)
127                .next_power_of_two()
128                .max(MIN_CAPACITY)
129        };
130
131        if target_cap <= self.slots.len() {
132            return;
133        }
134
135        let new_cap = target_cap;
136        let new_mask = new_cap - 1;
137
138        let new_slots: Vec<Slot<V>> = (0..new_cap)
139            .map(|_| Slot {
140                key: EMPTY,
141                value: MaybeUninit::uninit(),
142            })
143            .collect();
144
145        let old_slots = std::mem::replace(&mut self.slots, new_slots.into_boxed_slice());
146        let old_len = self.len;
147        self.len = usize::from(self.min_value.is_some());
148        self.mask = new_mask;
149
150        for slot in old_slots.iter() {
151            if slot.key != EMPTY {
152                // SAFETY: We are moving valid initialized values
153                let value = unsafe { slot.value.as_ptr().read() };
154                self.insert(slot.key, value);
155            }
156        }
157
158        debug_assert_eq!(self.len, old_len);
159    }
160
161    /// FxHash with pre-mixing - XOR the key with its shifted self before
162    /// multiplication to break stride patterns while preserving bijectivity.
163    /// This maintains 0 collisions for sequential keys while reducing strided
164    /// key collisions by ~65% (e.g., stride=1024 goes from 99,872 to 34,464).
165    #[inline(always)]
166    fn hash(key: i64) -> usize {
167        let k = key as u64;
168        let k = k ^ (k >> 16); // Pre-mix to break stride patterns (bijective)
169        k.wrapping_mul(0x517cc1b727220a95) as usize
170    }
171
172    #[inline(always)]
173    pub fn insert(&mut self, key: i64, value: V) -> Option<V> {
174        if key == EMPTY {
175            let old = self.min_value.replace(value);
176            if old.is_none() {
177                self.len += 1;
178            }
179            return old;
180        }
181
182        if self.len * LOAD_FACTOR_DEN >= self.slots.len() * LOAD_FACTOR_NUM {
183            self.grow();
184        }
185
186        let mask = self.mask;
187        let mut idx = Self::hash(key) & mask;
188
189        loop {
190            // SAFETY: idx is always in bounds due to masking with (capacity - 1).
191            let slot = unsafe { self.slots.get_unchecked_mut(idx) };
192
193            if slot.key == EMPTY {
194                // Empty slot - insert here
195                slot.key = key;
196                slot.value.write(value);
197                self.len += 1;
198                return None;
199            }
200
201            if slot.key == key {
202                // Key exists - replace value
203                // SAFETY: slot.key == key means this slot is occupied with initialized value.
204                let old = unsafe { slot.value.as_ptr().read() };
205                slot.value.write(value);
206                return Some(old);
207            }
208
209            idx = (idx + 1) & mask;
210        }
211    }
212
213    #[inline(always)]
214    pub fn get(&self, key: i64) -> Option<&V> {
215        if key == EMPTY {
216            return self.min_value.as_ref();
217        }
218
219        let mask = self.mask;
220        let mut idx = Self::hash(key) & mask;
221
222        loop {
223            // SAFETY: idx is always in bounds due to masking with (capacity - 1).
224            let slot = unsafe { self.slots.get_unchecked(idx) };
225
226            if slot.key == EMPTY {
227                return None;
228            }
229
230            if slot.key == key {
231                // SAFETY: slot.key == key means this slot is occupied with initialized value.
232                return Some(unsafe { slot.value.assume_init_ref() });
233            }
234
235            idx = (idx + 1) & mask;
236        }
237    }
238
239    #[inline(always)]
240    pub fn get_mut(&mut self, key: i64) -> Option<&mut V> {
241        if key == EMPTY {
242            return self.min_value.as_mut();
243        }
244
245        let mask = self.mask;
246        let mut idx = Self::hash(key) & mask;
247
248        // Find index first to avoid borrow issues
249        let found_idx = loop {
250            // SAFETY: idx is always in bounds due to masking with (capacity - 1).
251            let slot = unsafe { self.slots.get_unchecked(idx) };
252
253            if slot.key == EMPTY {
254                return None;
255            }
256
257            if slot.key == key {
258                break idx;
259            }
260
261            idx = (idx + 1) & mask;
262        };
263
264        // SAFETY: found_idx is valid and the slot at that index is occupied (key matched).
265        Some(unsafe {
266            self.slots
267                .get_unchecked_mut(found_idx)
268                .value
269                .assume_init_mut()
270        })
271    }
272
273    #[inline(always)]
274    pub fn contains_key(&self, key: i64) -> bool {
275        self.get(key).is_some()
276    }
277
278    #[inline(always)]
279    pub fn remove(&mut self, key: i64) -> Option<V> {
280        if key == EMPTY {
281            let value = self.min_value.take()?;
282            self.len -= 1;
283            if self.should_shrink() {
284                self.shrink();
285            }
286            return Some(value);
287        }
288
289        let mask = self.mask;
290        let mut idx = Self::hash(key) & mask;
291
292        // Find the key
293        loop {
294            // SAFETY: idx is always in bounds due to masking with (capacity - 1).
295            let slot = unsafe { self.slots.get_unchecked(idx) };
296
297            if slot.key == EMPTY {
298                return None;
299            }
300
301            if slot.key == key {
302                break;
303            }
304
305            idx = (idx + 1) & mask;
306        }
307
308        // Found - extract value
309        // SAFETY: idx is valid and slot is occupied (we just found the key).
310        let value = unsafe { self.slots.get_unchecked(idx).value.as_ptr().read() };
311        self.len -= 1;
312
313        // Backward shift deletion
314        let mut empty_idx = idx;
315        let mut next_idx = (idx + 1) & mask;
316
317        loop {
318            // SAFETY: next_idx is always in bounds due to masking.
319            let next_slot = unsafe { self.slots.get_unchecked(next_idx) };
320
321            if next_slot.key == EMPTY {
322                break;
323            }
324
325            let next_home = Self::hash(next_slot.key) & mask;
326
327            // Check if empty_idx is between next_home and next_idx (considering wrap)
328            let can_move = if next_home <= next_idx {
329                empty_idx >= next_home && empty_idx < next_idx
330            } else {
331                empty_idx >= next_home || empty_idx < next_idx
332            };
333
334            if can_move {
335                // Move entry back
336                // SAFETY: Both indices are in bounds, src slot is occupied, dst slot is empty.
337                // Derive both pointers from a single as_mut_ptr() call to avoid
338                // Stacked Borrows invalidation (as_ptr then as_mut_ptr conflicts).
339                unsafe {
340                    let base = self.slots.as_mut_ptr();
341                    let src = base.add(next_idx);
342                    let dst = base.add(empty_idx);
343                    (*dst).key = (*src).key;
344                    std::ptr::copy_nonoverlapping(
345                        (*src).value.as_ptr(),
346                        (*dst).value.as_mut_ptr(),
347                        1,
348                    );
349                }
350                empty_idx = next_idx;
351            }
352
353            next_idx = (next_idx + 1) & mask;
354        }
355
356        // SAFETY: empty_idx is in bounds and we're marking the now-empty slot.
357        unsafe {
358            self.slots.get_unchecked_mut(empty_idx).key = EMPTY;
359        }
360
361        // Check if we should shrink after removal
362        if self.should_shrink() {
363            self.shrink();
364        }
365
366        Some(value)
367    }
368
369    fn grow(&mut self) {
370        let new_cap = (self.slots.len() * 2).max(MIN_CAPACITY);
371        let new_mask = new_cap - 1;
372
373        let new_slots: Vec<Slot<V>> = (0..new_cap)
374            .map(|_| Slot {
375                key: EMPTY,
376                value: MaybeUninit::uninit(),
377            })
378            .collect();
379
380        let old_slots = std::mem::replace(&mut self.slots, new_slots.into_boxed_slice());
381        let old_len = self.len;
382        self.len = usize::from(self.min_value.is_some());
383        self.mask = new_mask;
384
385        for slot in Vec::from(old_slots) {
386            if slot.key != EMPTY {
387                // SAFETY: slot.key != EMPTY means the value is initialized.
388                let value = unsafe { slot.value.assume_init() };
389                self.insert(slot.key, value);
390            }
391        }
392
393        debug_assert_eq!(self.len, old_len);
394    }
395
396    /// Check if we should shrink: len < capacity / SHRINK_DIVISOR
397    /// Only shrink if capacity > MIN_SHRINK_CAPACITY to avoid thrashing
398    #[inline]
399    fn should_shrink(&self) -> bool {
400        let cap = self.slots.len();
401        cap > MIN_SHRINK_CAPACITY && self.len < cap / SHRINK_DIVISOR
402    }
403
404    /// Shrink the table to fit current entries
405    fn shrink(&mut self) {
406        // Calculate new capacity needed for current entries
407        let new_cap = if self.len == 0 {
408            MIN_CAPACITY
409        } else {
410            self.len
411                .saturating_mul(LOAD_FACTOR_DEN)
412                .saturating_div(LOAD_FACTOR_NUM)
413                .next_power_of_two()
414                .max(MIN_CAPACITY)
415        };
416
417        if new_cap >= self.slots.len() {
418            return; // No need to shrink
419        }
420
421        let new_mask = new_cap - 1;
422
423        let new_slots: Vec<Slot<V>> = (0..new_cap)
424            .map(|_| Slot {
425                key: EMPTY,
426                value: MaybeUninit::uninit(),
427            })
428            .collect();
429
430        let old_slots = std::mem::replace(&mut self.slots, new_slots.into_boxed_slice());
431        let old_len = self.len;
432        self.len = usize::from(self.min_value.is_some());
433        self.mask = new_mask;
434
435        for slot in Vec::from(old_slots) {
436            if slot.key != EMPTY {
437                // SAFETY: slot.key != EMPTY means the value is initialized.
438                let value = unsafe { slot.value.assume_init() };
439                self.insert(slot.key, value);
440            }
441        }
442
443        debug_assert_eq!(self.len, old_len);
444    }
445
446    /// Shrink the map to fit its current contents, releasing excess memory.
447    ///
448    /// Call this after removing many entries to reclaim memory.
449    pub fn shrink_to_fit(&mut self) {
450        self.shrink();
451    }
452
453    pub fn clear(&mut self) {
454        if let Some(value) = self.min_value.take() {
455            self.len -= 1;
456            drop(value);
457        }
458        for slot in self.slots.iter_mut() {
459            if slot.key != EMPTY {
460                // Retire the slot and its cardinality before invoking user
461                // Drop code. If Drop unwinds, the remaining occupied slots and
462                // len still describe the same valid partial map.
463                slot.key = EMPTY;
464                self.len -= 1;
465                // SAFETY: The old non-empty key proved the value initialized.
466                unsafe {
467                    std::ptr::drop_in_place(slot.value.as_mut_ptr());
468                }
469            }
470        }
471        debug_assert_eq!(self.len, 0);
472    }
473
474    #[inline]
475    pub fn iter(&self) -> impl Iterator<Item = (i64, &V)> {
476        self.min_value
477            .iter()
478            .map(|value| (EMPTY, value))
479            .chain(self.slots.iter().filter_map(|slot| {
480                if slot.key != EMPTY {
481                    // SAFETY: slot.key != EMPTY means the value is initialized.
482                    Some((slot.key, unsafe { slot.value.assume_init_ref() }))
483                } else {
484                    None
485                }
486            }))
487    }
488
489    #[inline]
490    pub fn keys(&self) -> impl Iterator<Item = i64> + '_ {
491        self.min_value
492            .iter()
493            .map(|_| EMPTY)
494            .chain(
495                self.slots
496                    .iter()
497                    .filter_map(|s| if s.key != EMPTY { Some(s.key) } else { None }),
498            )
499    }
500
501    #[inline]
502    pub fn values(&self) -> impl Iterator<Item = &V> {
503        self.min_value
504            .iter()
505            .chain(self.slots.iter().filter_map(|slot| {
506                if slot.key != EMPTY {
507                    // SAFETY: slot.key != EMPTY means the value is initialized.
508                    Some(unsafe { slot.value.assume_init_ref() })
509                } else {
510                    None
511                }
512            }))
513    }
514
515    #[inline]
516    pub fn iter_mut(&mut self) -> impl Iterator<Item = (i64, &mut V)> {
517        self.min_value.iter_mut().map(|value| (EMPTY, value)).chain(
518            self.slots.iter_mut().filter_map(|slot| {
519                if slot.key != EMPTY {
520                    // SAFETY: slot.key != EMPTY means the value is initialized.
521                    Some((slot.key, unsafe { slot.value.assume_init_mut() }))
522                } else {
523                    None
524                }
525            }),
526        )
527    }
528
529    /// Retains only the elements specified by the predicate.
530    ///
531    /// In other words, remove all entries `(k, v)` where `f(k, &mut v)` returns `false`.
532    pub fn retain<F>(&mut self, mut f: F)
533    where
534        F: FnMut(i64, &mut V) -> bool,
535    {
536        let remove_min = self
537            .min_value
538            .as_mut()
539            .is_some_and(|value| !f(EMPTY, value));
540        if remove_min {
541            let value = self.min_value.take();
542            self.len -= 1;
543            drop(value);
544        }
545
546        // Collect keys to remove (can't remove while iterating due to backward-shift)
547        let keys_to_remove: Vec<i64> = self
548            .slots
549            .iter_mut()
550            .filter_map(|slot| {
551                if slot.key != EMPTY {
552                    // SAFETY: slot.key != EMPTY means the value is initialized.
553                    let value = unsafe { slot.value.assume_init_mut() };
554                    if f(slot.key, value) {
555                        None // Keep this entry
556                    } else {
557                        Some(slot.key) // Mark for removal
558                    }
559                } else {
560                    None
561                }
562            })
563            .collect();
564
565        for key in keys_to_remove {
566            self.remove(key);
567        }
568    }
569
570    /// Drains all entries from the map, returning an iterator over them
571    #[inline]
572    pub fn drain(&mut self) -> Drain<V> {
573        // Take slots and replace with fresh minimum-capacity slots
574        let old_slots = std::mem::replace(
575            &mut self.slots,
576            (0..MIN_CAPACITY)
577                .map(|_| Slot {
578                    key: EMPTY,
579                    value: MaybeUninit::uninit(),
580                })
581                .collect::<Vec<_>>()
582                .into_boxed_slice(),
583        );
584        let min_value = self.min_value.take();
585        self.len = 0;
586        self.mask = MIN_CAPACITY - 1;
587        Drain {
588            slots: old_slots,
589            min_value,
590            pos: 0,
591        }
592    }
593
594    #[inline(always)]
595    pub fn entry(&mut self, key: i64) -> Entry<'_, V> {
596        if key == EMPTY {
597            return if self.min_value.is_some() {
598                Entry::Occupied(OccupiedEntry {
599                    map: self,
600                    idx: 0,
601                    is_min: true,
602                })
603            } else {
604                Entry::Vacant(VacantEntry {
605                    map: self,
606                    key,
607                    idx: 0,
608                    is_min: true,
609                })
610            };
611        }
612
613        let mask = self.mask;
614        let mut idx = Self::hash(key) & mask;
615
616        // First, check if key exists WITHOUT growing
617        loop {
618            // SAFETY: idx is always in bounds due to masking with (capacity - 1).
619            let slot = unsafe { self.slots.get_unchecked(idx) };
620
621            if slot.key == EMPTY {
622                // Key not found - now check if we need to grow before insertion
623                if self.len * LOAD_FACTOR_DEN >= self.slots.len() * LOAD_FACTOR_NUM {
624                    self.grow();
625                    // After grow, need to find the slot again
626                    let new_mask = self.mask;
627                    let mut new_idx = Self::hash(key) & new_mask;
628                    loop {
629                        // SAFETY: new_idx is always in bounds due to masking.
630                        let slot = unsafe { self.slots.get_unchecked(new_idx) };
631                        if slot.key == EMPTY {
632                            return Entry::Vacant(VacantEntry {
633                                map: self,
634                                key,
635                                idx: new_idx,
636                                is_min: false,
637                            });
638                        }
639                        new_idx = (new_idx + 1) & new_mask;
640                    }
641                }
642                return Entry::Vacant(VacantEntry {
643                    map: self,
644                    key,
645                    idx,
646                    is_min: false,
647                });
648            }
649
650            if slot.key == key {
651                return Entry::Occupied(OccupiedEntry {
652                    map: self,
653                    idx,
654                    is_min: false,
655                });
656            }
657
658            idx = (idx + 1) & mask;
659        }
660    }
661}
662
663impl<V> Drop for I64Map<V> {
664    fn drop(&mut self) {
665        for slot in self.slots.iter_mut() {
666            if slot.key != EMPTY {
667                // SAFETY: slot.key != EMPTY means the value is initialized.
668                unsafe {
669                    std::ptr::drop_in_place(slot.value.as_mut_ptr());
670                }
671            }
672        }
673    }
674}
675
676pub enum Entry<'a, V> {
677    Occupied(OccupiedEntry<'a, V>),
678    Vacant(VacantEntry<'a, V>),
679}
680
681impl<'a, V> Entry<'a, V> {
682    #[inline(always)]
683    pub fn or_insert(self, default: V) -> &'a mut V {
684        match self {
685            Entry::Occupied(e) => e.into_mut(),
686            Entry::Vacant(e) => e.insert(default),
687        }
688    }
689
690    #[inline(always)]
691    pub fn or_insert_with<F: FnOnce() -> V>(self, f: F) -> &'a mut V {
692        match self {
693            Entry::Occupied(e) => e.into_mut(),
694            Entry::Vacant(e) => e.insert(f()),
695        }
696    }
697
698    #[inline(always)]
699    pub fn or_default(self) -> &'a mut V
700    where
701        V: Default,
702    {
703        match self {
704            Entry::Occupied(e) => e.into_mut(),
705            Entry::Vacant(e) => e.insert(V::default()),
706        }
707    }
708
709    #[inline(always)]
710    pub fn and_modify<F: FnOnce(&mut V)>(self, f: F) -> Self {
711        match self {
712            Entry::Occupied(mut e) => {
713                f(e.get_mut());
714                Entry::Occupied(e)
715            }
716            Entry::Vacant(e) => Entry::Vacant(e),
717        }
718    }
719}
720
721pub struct OccupiedEntry<'a, V> {
722    map: &'a mut I64Map<V>,
723    idx: usize,
724    is_min: bool,
725}
726
727impl<'a, V> OccupiedEntry<'a, V> {
728    #[inline(always)]
729    pub fn get(&self) -> &V {
730        if self.is_min {
731            return self
732                .map
733                .min_value
734                .as_ref()
735                .expect("occupied minimum entry must have a value");
736        }
737        // SAFETY: OccupiedEntry is only created for occupied slots, so idx is
738        // valid and the value at that index is initialized.
739        unsafe {
740            self.map
741                .slots
742                .get_unchecked(self.idx)
743                .value
744                .assume_init_ref()
745        }
746    }
747
748    #[inline(always)]
749    pub fn get_mut(&mut self) -> &mut V {
750        if self.is_min {
751            return self
752                .map
753                .min_value
754                .as_mut()
755                .expect("occupied minimum entry must have a value");
756        }
757        // SAFETY: OccupiedEntry is only created for occupied slots, so idx is
758        // valid and the value at that index is initialized.
759        unsafe {
760            self.map
761                .slots
762                .get_unchecked_mut(self.idx)
763                .value
764                .assume_init_mut()
765        }
766    }
767
768    #[inline(always)]
769    pub fn into_mut(self) -> &'a mut V {
770        if self.is_min {
771            return self
772                .map
773                .min_value
774                .as_mut()
775                .expect("occupied minimum entry must have a value");
776        }
777        // SAFETY: OccupiedEntry is only created for occupied slots, so idx is
778        // valid and the value at that index is initialized.
779        unsafe {
780            self.map
781                .slots
782                .get_unchecked_mut(self.idx)
783                .value
784                .assume_init_mut()
785        }
786    }
787
788    #[inline(always)]
789    pub fn insert(&mut self, value: V) -> V {
790        if self.is_min {
791            return self
792                .map
793                .min_value
794                .replace(value)
795                .expect("occupied minimum entry must have a value");
796        }
797        // SAFETY: OccupiedEntry is only created for occupied slots.
798        let slot = unsafe { self.map.slots.get_unchecked_mut(self.idx) };
799        // SAFETY: The slot is occupied, so value is initialized.
800        let old = unsafe { slot.value.as_ptr().read() };
801        slot.value.write(value);
802        old
803    }
804
805    #[inline(always)]
806    pub fn remove(self) -> V {
807        if self.is_min {
808            self.map.len -= 1;
809            return self
810                .map
811                .min_value
812                .take()
813                .expect("occupied minimum entry must have a value");
814        }
815        // Extract value directly - we already have the index
816        // SAFETY: OccupiedEntry is only created for occupied slots.
817        let key = unsafe { self.map.slots.get_unchecked(self.idx).key };
818        // SAFETY: The slot is occupied, so value is initialized.
819        let value = unsafe { self.map.slots.get_unchecked(self.idx).value.as_ptr().read() };
820        self.map.len -= 1;
821
822        // Backward shift deletion at known index
823        let mask = self.map.mask;
824        let mut empty_idx = self.idx;
825        let mut next_idx = (self.idx + 1) & mask;
826
827        loop {
828            // SAFETY: next_idx is always in bounds due to masking.
829            let next_slot = unsafe { self.map.slots.get_unchecked(next_idx) };
830
831            if next_slot.key == EMPTY {
832                break;
833            }
834
835            let next_home = I64Map::<V>::hash(next_slot.key) & mask;
836
837            // Check if empty_idx is between next_home and next_idx (considering wrap)
838            let can_move = if next_home <= next_idx {
839                empty_idx >= next_home && empty_idx < next_idx
840            } else {
841                empty_idx >= next_home || empty_idx < next_idx
842            };
843
844            if can_move {
845                // Move entry back
846                // SAFETY: Both indices are in bounds, src slot is occupied, dst slot is empty.
847                // Derive both pointers from a single as_mut_ptr() call to avoid
848                // Stacked Borrows invalidation (as_ptr then as_mut_ptr conflicts).
849                unsafe {
850                    let base = self.map.slots.as_mut_ptr();
851                    let src = base.add(next_idx);
852                    let dst = base.add(empty_idx);
853                    (*dst).key = (*src).key;
854                    std::ptr::copy_nonoverlapping(
855                        (*src).value.as_ptr(),
856                        (*dst).value.as_mut_ptr(),
857                        1,
858                    );
859                }
860                empty_idx = next_idx;
861            }
862
863            next_idx = (next_idx + 1) & mask;
864        }
865
866        // SAFETY: empty_idx is in bounds and we're marking the now-empty slot.
867        unsafe {
868            self.map.slots.get_unchecked_mut(empty_idx).key = EMPTY;
869        }
870
871        // Suppress unused variable warning
872        let _ = key;
873
874        value
875    }
876}
877
878pub struct VacantEntry<'a, V> {
879    map: &'a mut I64Map<V>,
880    key: i64,
881    idx: usize,
882    is_min: bool,
883}
884
885impl<'a, V> VacantEntry<'a, V> {
886    #[inline(always)]
887    pub fn key(&self) -> i64 {
888        self.key
889    }
890
891    #[inline(always)]
892    pub fn insert(self, value: V) -> &'a mut V {
893        if self.is_min {
894            self.map.len += 1;
895            return self.map.min_value.insert(value);
896        }
897        // Direct insert at pre-computed index - NO re-lookup needed
898        // SAFETY: VacantEntry stores a valid idx that was found during entry() lookup.
899        let slot = unsafe { self.map.slots.get_unchecked_mut(self.idx) };
900        slot.key = self.key;
901        slot.value.write(value);
902        self.map.len += 1;
903        // SAFETY: We just wrote the value, so it's initialized.
904        unsafe { slot.value.assume_init_mut() }
905    }
906}
907
908/// Owning iterator over the entries of an I64Map
909pub struct IntoIter<V> {
910    slots: Box<[Slot<V>]>,
911    min_value: Option<V>,
912    pos: usize,
913}
914
915impl<V> Iterator for IntoIter<V> {
916    type Item = (i64, V);
917
918    #[inline]
919    fn next(&mut self) -> Option<Self::Item> {
920        if let Some(value) = self.min_value.take() {
921            return Some((EMPTY, value));
922        }
923        while self.pos < self.slots.len() {
924            let slot = &mut self.slots[self.pos];
925            self.pos += 1;
926
927            if slot.key != EMPTY {
928                let key = slot.key;
929                // SAFETY: slot.key != EMPTY means the value is initialized.
930                let value = unsafe { slot.value.as_ptr().read() };
931                slot.key = EMPTY; // Mark as consumed to prevent double-drop
932                return Some((key, value));
933            }
934        }
935        None
936    }
937
938    #[inline]
939    fn size_hint(&self) -> (usize, Option<usize>) {
940        (
941            0,
942            Some(self.slots.len() - self.pos + usize::from(self.min_value.is_some())),
943        )
944    }
945}
946
947impl<V> Drop for IntoIter<V> {
948    fn drop(&mut self) {
949        // Drop remaining unconsumed elements
950        while self.pos < self.slots.len() {
951            let slot = &mut self.slots[self.pos];
952            self.pos += 1;
953
954            if slot.key != EMPTY {
955                // SAFETY: slot.key != EMPTY means the value is initialized.
956                unsafe {
957                    std::ptr::drop_in_place(slot.value.as_mut_ptr());
958                }
959                slot.key = EMPTY; // Mark as dropped
960            }
961        }
962    }
963}
964
965impl<V> IntoIterator for I64Map<V> {
966    type Item = (i64, V);
967    type IntoIter = IntoIter<V>;
968
969    fn into_iter(mut self) -> Self::IntoIter {
970        let slots = std::mem::take(&mut self.slots);
971        let min_value = self.min_value.take();
972        self.len = 0; // Prevent drop from cleaning up values we're moving out
973        IntoIter {
974            slots,
975            min_value,
976            pos: 0,
977        }
978    }
979}
980
981/// Draining iterator over the entries of an I64Map
982pub struct Drain<V> {
983    slots: Box<[Slot<V>]>,
984    min_value: Option<V>,
985    pos: usize,
986}
987
988// =============================================================================
989// I64Set - High-performance HashSet for i64 keys
990// =============================================================================
991
992/// High-performance HashSet for i64 keys.
993///
994/// Uses the same optimizations as I64Map:
995/// - i64::MIN as the in-table empty sentinel with that logical value out of band
996/// - FxHash with pre-mixing (XOR>>16 before multiply) - 0 sequential collisions
997/// - Backward-shift deletion (no tombstones)
998///
999/// Supports the full `i64` value domain.
1000pub struct I64Set {
1001    slots: Box<[i64]>,
1002    has_min: bool,
1003    len: usize,
1004    mask: usize,
1005}
1006
1007impl Clone for I64Set {
1008    fn clone(&self) -> Self {
1009        let mut new_set = Self::with_capacity(self.len);
1010        for key in self.iter() {
1011            new_set.insert(key);
1012        }
1013        new_set
1014    }
1015}
1016
1017impl std::fmt::Debug for I64Set {
1018    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1019        f.debug_set().entries(self.iter()).finish()
1020    }
1021}
1022
1023impl Default for I64Set {
1024    #[inline(always)]
1025    fn default() -> Self {
1026        Self::new()
1027    }
1028}
1029
1030impl I64Set {
1031    #[inline(always)]
1032    pub fn new() -> Self {
1033        Self::with_capacity(0)
1034    }
1035
1036    pub fn with_capacity(capacity: usize) -> Self {
1037        let cap = if capacity == 0 {
1038            MIN_CAPACITY
1039        } else {
1040            capacity
1041                .saturating_mul(LOAD_FACTOR_DEN)
1042                .saturating_div(LOAD_FACTOR_NUM)
1043                .next_power_of_two()
1044                .max(MIN_CAPACITY)
1045        };
1046
1047        let slots: Vec<i64> = vec![EMPTY; cap];
1048
1049        Self {
1050            slots: slots.into_boxed_slice(),
1051            has_min: false,
1052            len: 0,
1053            mask: cap - 1,
1054        }
1055    }
1056
1057    #[inline(always)]
1058    pub fn len(&self) -> usize {
1059        self.len
1060    }
1061
1062    #[inline(always)]
1063    pub fn is_empty(&self) -> bool {
1064        self.len == 0
1065    }
1066
1067    #[inline(always)]
1068    pub fn capacity(&self) -> usize {
1069        self.slots.len()
1070    }
1071
1072    /// Reserves capacity for at least `additional` more elements to be inserted
1073    /// in the set. The collection may reserve more space to avoid frequent reallocations.
1074    pub fn reserve(&mut self, additional: usize) {
1075        let target_len = self.len + additional;
1076        let target_cap = if target_len == 0 {
1077            MIN_CAPACITY
1078        } else {
1079            target_len
1080                .saturating_mul(LOAD_FACTOR_DEN)
1081                .saturating_div(LOAD_FACTOR_NUM)
1082                .next_power_of_two()
1083                .max(MIN_CAPACITY)
1084        };
1085
1086        if target_cap <= self.slots.len() {
1087            return;
1088        }
1089
1090        let new_cap = target_cap;
1091        let new_mask = new_cap - 1;
1092
1093        let new_slots: Vec<i64> = vec![EMPTY; new_cap];
1094        let old_slots = std::mem::replace(&mut self.slots, new_slots.into_boxed_slice());
1095        let old_len = self.len;
1096        self.len = usize::from(self.has_min);
1097        self.mask = new_mask;
1098
1099        for slot in old_slots.iter() {
1100            if *slot != EMPTY {
1101                self.insert(*slot);
1102            }
1103        }
1104
1105        debug_assert_eq!(self.len, old_len);
1106    }
1107
1108    /// FxHash with pre-mixing - same as I64Map
1109    #[inline(always)]
1110    fn hash(key: i64) -> usize {
1111        let k = key as u64;
1112        let k = k ^ (k >> 16);
1113        k.wrapping_mul(0x517cc1b727220a95) as usize
1114    }
1115
1116    /// Insert a value into the set. Returns true if the value was newly inserted.
1117    #[inline(always)]
1118    pub fn insert(&mut self, key: i64) -> bool {
1119        if key == EMPTY {
1120            if self.has_min {
1121                return false;
1122            }
1123            self.has_min = true;
1124            self.len += 1;
1125            return true;
1126        }
1127
1128        if self.len * LOAD_FACTOR_DEN >= self.slots.len() * LOAD_FACTOR_NUM {
1129            self.grow();
1130        }
1131
1132        let mask = self.mask;
1133        let mut idx = Self::hash(key) & mask;
1134
1135        loop {
1136            // SAFETY: idx is always (hash & mask), where mask = slots.len() - 1.
1137            // Since slots.len() is a power of 2, idx is always in bounds.
1138            let slot = unsafe { *self.slots.get_unchecked(idx) };
1139
1140            if slot == EMPTY {
1141                // SAFETY: Same bounds reasoning as above - idx is always valid.
1142                unsafe { *self.slots.get_unchecked_mut(idx) = key };
1143                self.len += 1;
1144                return true;
1145            }
1146
1147            if slot == key {
1148                return false; // Already exists
1149            }
1150
1151            idx = (idx + 1) & mask;
1152        }
1153    }
1154
1155    #[inline(always)]
1156    pub fn contains(&self, key: i64) -> bool {
1157        if key == EMPTY {
1158            return self.has_min;
1159        }
1160
1161        let mask = self.mask;
1162        let mut idx = Self::hash(key) & mask;
1163
1164        loop {
1165            // SAFETY: idx is always (hash & mask), where mask = slots.len() - 1.
1166            // Since slots.len() is a power of 2, idx is always in bounds.
1167            let slot = unsafe { *self.slots.get_unchecked(idx) };
1168
1169            if slot == EMPTY {
1170                return false;
1171            }
1172
1173            if slot == key {
1174                return true;
1175            }
1176
1177            idx = (idx + 1) & mask;
1178        }
1179    }
1180
1181    #[inline(always)]
1182    pub fn remove(&mut self, key: i64) -> bool {
1183        if key == EMPTY {
1184            if !self.has_min {
1185                return false;
1186            }
1187            self.has_min = false;
1188            self.len -= 1;
1189            if self.should_shrink() {
1190                self.shrink();
1191            }
1192            return true;
1193        }
1194
1195        let mask = self.mask;
1196        let mut idx = Self::hash(key) & mask;
1197
1198        // Find the key
1199        loop {
1200            // SAFETY: idx is always (hash & mask), where mask = slots.len() - 1.
1201            // Since slots.len() is a power of 2, idx is always in bounds.
1202            let slot = unsafe { *self.slots.get_unchecked(idx) };
1203
1204            if slot == EMPTY {
1205                return false;
1206            }
1207
1208            if slot == key {
1209                break;
1210            }
1211
1212            idx = (idx + 1) & mask;
1213        }
1214
1215        self.len -= 1;
1216
1217        // Backward shift deletion
1218        let mut empty_idx = idx;
1219        let mut next_idx = (idx + 1) & mask;
1220
1221        loop {
1222            // SAFETY: next_idx is always (some_value & mask), where mask = slots.len() - 1.
1223            // Since slots.len() is a power of 2, next_idx is always in bounds.
1224            let next_slot = unsafe { *self.slots.get_unchecked(next_idx) };
1225
1226            if next_slot == EMPTY {
1227                break;
1228            }
1229
1230            let next_home = Self::hash(next_slot) & mask;
1231
1232            let can_move = if next_home <= next_idx {
1233                empty_idx >= next_home && empty_idx < next_idx
1234            } else {
1235                empty_idx >= next_home || empty_idx < next_idx
1236            };
1237
1238            if can_move {
1239                // SAFETY: empty_idx was either the original idx (valid) or a previous
1240                // next_idx (also valid by the same mask reasoning).
1241                unsafe {
1242                    *self.slots.get_unchecked_mut(empty_idx) = next_slot;
1243                }
1244                empty_idx = next_idx;
1245            }
1246
1247            next_idx = (next_idx + 1) & mask;
1248        }
1249
1250        // SAFETY: empty_idx is always a valid index (same mask reasoning as above).
1251        unsafe {
1252            *self.slots.get_unchecked_mut(empty_idx) = EMPTY;
1253        }
1254
1255        // Check if we should shrink after removal
1256        if self.should_shrink() {
1257            self.shrink();
1258        }
1259
1260        true
1261    }
1262
1263    fn grow(&mut self) {
1264        let new_cap = (self.slots.len() * 2).max(MIN_CAPACITY);
1265        let new_mask = new_cap - 1;
1266
1267        let new_slots: Vec<i64> = vec![EMPTY; new_cap];
1268        let old_slots = std::mem::replace(&mut self.slots, new_slots.into_boxed_slice());
1269        let old_len = self.len;
1270        self.len = usize::from(self.has_min);
1271        self.mask = new_mask;
1272
1273        for slot in old_slots.iter() {
1274            if *slot != EMPTY {
1275                self.insert(*slot);
1276            }
1277        }
1278
1279        debug_assert_eq!(self.len, old_len);
1280    }
1281
1282    /// Check if we should shrink: len < capacity / SHRINK_DIVISOR
1283    /// Only shrink if capacity > MIN_SHRINK_CAPACITY to avoid thrashing
1284    #[inline]
1285    fn should_shrink(&self) -> bool {
1286        let cap = self.slots.len();
1287        cap > MIN_SHRINK_CAPACITY && self.len < cap / SHRINK_DIVISOR
1288    }
1289
1290    /// Shrink the set to fit current entries
1291    fn shrink(&mut self) {
1292        // Calculate new capacity needed for current entries
1293        let new_cap = if self.len == 0 {
1294            MIN_CAPACITY
1295        } else {
1296            self.len
1297                .saturating_mul(LOAD_FACTOR_DEN)
1298                .saturating_div(LOAD_FACTOR_NUM)
1299                .next_power_of_two()
1300                .max(MIN_CAPACITY)
1301        };
1302
1303        if new_cap >= self.slots.len() {
1304            return; // No need to shrink
1305        }
1306
1307        let new_mask = new_cap - 1;
1308
1309        let new_slots: Vec<i64> = vec![EMPTY; new_cap];
1310        let old_slots = std::mem::replace(&mut self.slots, new_slots.into_boxed_slice());
1311        let old_len = self.len;
1312        self.len = usize::from(self.has_min);
1313        self.mask = new_mask;
1314
1315        for slot in old_slots.iter() {
1316            if *slot != EMPTY {
1317                self.insert(*slot);
1318            }
1319        }
1320
1321        debug_assert_eq!(self.len, old_len);
1322    }
1323
1324    /// Shrink the set to fit its current contents, releasing excess memory.
1325    ///
1326    /// Call this after removing many entries to reclaim memory.
1327    pub fn shrink_to_fit(&mut self) {
1328        self.shrink();
1329    }
1330
1331    pub fn clear(&mut self) {
1332        for slot in self.slots.iter_mut() {
1333            *slot = EMPTY;
1334        }
1335        self.has_min = false;
1336        self.len = 0;
1337    }
1338
1339    #[inline]
1340    pub fn iter(&self) -> impl Iterator<Item = i64> + '_ {
1341        std::iter::once(EMPTY).filter(|_| self.has_min).chain(
1342            self.slots
1343                .iter()
1344                .filter_map(|&slot| if slot != EMPTY { Some(slot) } else { None }),
1345        )
1346    }
1347
1348    /// Drains all values from the set, returning an iterator over them
1349    #[inline]
1350    pub fn drain(&mut self) -> impl Iterator<Item = i64> + '_ {
1351        let len = self.len;
1352        let has_min = std::mem::take(&mut self.has_min);
1353        self.len = 0;
1354        I64SetDrain {
1355            slots: self.slots.iter_mut(),
1356            has_min,
1357            remaining: len,
1358        }
1359    }
1360}
1361
1362struct I64SetDrain<'a> {
1363    slots: std::slice::IterMut<'a, i64>,
1364    has_min: bool,
1365    remaining: usize,
1366}
1367
1368impl Iterator for I64SetDrain<'_> {
1369    type Item = i64;
1370
1371    fn next(&mut self) -> Option<Self::Item> {
1372        if std::mem::take(&mut self.has_min) {
1373            self.remaining -= 1;
1374            return Some(EMPTY);
1375        }
1376        while self.remaining > 0 {
1377            let slot = self.slots.next()?;
1378            if *slot != EMPTY {
1379                let value = *slot;
1380                *slot = EMPTY;
1381                self.remaining -= 1;
1382                return Some(value);
1383            }
1384        }
1385        None
1386    }
1387
1388    fn size_hint(&self) -> (usize, Option<usize>) {
1389        (self.remaining, Some(self.remaining))
1390    }
1391}
1392
1393impl ExactSizeIterator for I64SetDrain<'_> {}
1394
1395impl Drop for I64SetDrain<'_> {
1396    fn drop(&mut self) {
1397        for _ in self.by_ref() {}
1398    }
1399}
1400
1401impl IntoIterator for I64Set {
1402    type Item = i64;
1403    type IntoIter = I64SetIntoIter;
1404
1405    fn into_iter(self) -> Self::IntoIter {
1406        I64SetIntoIter {
1407            slots: self.slots,
1408            has_min: self.has_min,
1409            pos: 0,
1410        }
1411    }
1412}
1413
1414/// Owning iterator over the values of an I64Set
1415pub struct I64SetIntoIter {
1416    slots: Box<[i64]>,
1417    has_min: bool,
1418    pos: usize,
1419}
1420
1421impl Iterator for I64SetIntoIter {
1422    type Item = i64;
1423
1424    #[inline]
1425    fn next(&mut self) -> Option<Self::Item> {
1426        if std::mem::take(&mut self.has_min) {
1427            return Some(EMPTY);
1428        }
1429        while self.pos < self.slots.len() {
1430            let slot = self.slots[self.pos];
1431            self.pos += 1;
1432
1433            if slot != EMPTY {
1434                return Some(slot);
1435            }
1436        }
1437        None
1438    }
1439
1440    #[inline]
1441    fn size_hint(&self) -> (usize, Option<usize>) {
1442        (
1443            0,
1444            Some(self.slots.len() - self.pos + usize::from(self.has_min)),
1445        )
1446    }
1447}
1448
1449impl std::iter::FromIterator<i64> for I64Set {
1450    fn from_iter<T: IntoIterator<Item = i64>>(iter: T) -> Self {
1451        let iter = iter.into_iter();
1452        let (lower, _) = iter.size_hint();
1453        let mut set = I64Set::with_capacity(lower);
1454        for key in iter {
1455            set.insert(key);
1456        }
1457        set
1458    }
1459}
1460
1461impl Extend<i64> for I64Set {
1462    fn extend<T: IntoIterator<Item = i64>>(&mut self, iter: T) {
1463        for key in iter {
1464            self.insert(key);
1465        }
1466    }
1467}
1468
1469impl<V> Iterator for Drain<V> {
1470    type Item = (i64, V);
1471
1472    #[inline]
1473    fn next(&mut self) -> Option<Self::Item> {
1474        if let Some(value) = self.min_value.take() {
1475            return Some((EMPTY, value));
1476        }
1477        while self.pos < self.slots.len() {
1478            let slot = &mut self.slots[self.pos];
1479            self.pos += 1;
1480
1481            if slot.key != EMPTY {
1482                let key = slot.key;
1483                // SAFETY: slot.key != EMPTY means the value is initialized.
1484                let value = unsafe { slot.value.as_ptr().read() };
1485                slot.key = EMPTY; // Mark as consumed to prevent double-drop
1486                return Some((key, value));
1487            }
1488        }
1489        None
1490    }
1491
1492    #[inline]
1493    fn size_hint(&self) -> (usize, Option<usize>) {
1494        (
1495            0,
1496            Some(self.slots.len() - self.pos + usize::from(self.min_value.is_some())),
1497        )
1498    }
1499}
1500
1501impl<V> Drop for Drain<V> {
1502    fn drop(&mut self) {
1503        // Consume remaining elements to ensure they're dropped
1504        for _ in self.by_ref() {}
1505    }
1506}
1507
1508#[cfg(test)]
1509mod tests {
1510    use super::*;
1511    use std::cell::RefCell;
1512    use std::rc::Rc;
1513
1514    struct PanicOnFirstDrop {
1515        panicked: Rc<std::cell::Cell<bool>>,
1516    }
1517
1518    impl Drop for PanicOnFirstDrop {
1519        fn drop(&mut self) {
1520            if !self.panicked.replace(true) {
1521                panic!("intentional drop panic");
1522            }
1523        }
1524    }
1525
1526    #[test]
1527    fn test_mutation_state_before_unwind_i64_map_clear() {
1528        let panicked = Rc::new(std::cell::Cell::new(false));
1529        let mut map = std::mem::ManuallyDrop::new(I64Map::new());
1530        for key in 1..=3 {
1531            map.insert(
1532                key,
1533                PanicOnFirstDrop {
1534                    panicked: Rc::clone(&panicked),
1535                },
1536            );
1537        }
1538
1539        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| map.clear()));
1540
1541        assert!(result.is_err());
1542        assert_eq!(map.len(), 2, "clear must retire each slot before Drop");
1543    }
1544
1545    /// Helper struct to track drops
1546    struct DropTracker {
1547        count: Rc<RefCell<usize>>,
1548    }
1549
1550    impl DropTracker {
1551        fn new(count: Rc<RefCell<usize>>) -> Self {
1552            Self { count }
1553        }
1554    }
1555
1556    impl Drop for DropTracker {
1557        fn drop(&mut self) {
1558            *self.count.borrow_mut() += 1;
1559        }
1560    }
1561
1562    #[test]
1563    fn test_into_iter_partial_consume_drops_remaining() {
1564        let drop_count = Rc::new(RefCell::new(0));
1565
1566        let mut map = I64Map::new();
1567        map.insert(1, DropTracker::new(Rc::clone(&drop_count)));
1568        map.insert(2, DropTracker::new(Rc::clone(&drop_count)));
1569        map.insert(3, DropTracker::new(Rc::clone(&drop_count)));
1570
1571        // Only consume one element
1572        let mut iter = map.into_iter();
1573        let _ = iter.next(); // Consume 1 item
1574
1575        // Drop count should be 1 (the consumed item)
1576        assert_eq!(*drop_count.borrow(), 1);
1577
1578        // Drop the iterator without consuming remaining elements
1579        drop(iter);
1580
1581        // All 3 items should now be dropped
1582        assert_eq!(
1583            *drop_count.borrow(),
1584            3,
1585            "Memory leak detected! Only {} items dropped",
1586            *drop_count.borrow()
1587        );
1588    }
1589
1590    #[test]
1591    fn test_into_iter_no_consume_drops_all() {
1592        let drop_count = Rc::new(RefCell::new(0));
1593
1594        let mut map = I64Map::new();
1595        map.insert(1, DropTracker::new(Rc::clone(&drop_count)));
1596        map.insert(2, DropTracker::new(Rc::clone(&drop_count)));
1597        map.insert(3, DropTracker::new(Rc::clone(&drop_count)));
1598
1599        // Don't consume any elements
1600        let iter = map.into_iter();
1601        drop(iter);
1602
1603        // All 3 items should be dropped
1604        assert_eq!(
1605            *drop_count.borrow(),
1606            3,
1607            "Memory leak detected! Only {} items dropped",
1608            *drop_count.borrow()
1609        );
1610    }
1611
1612    #[test]
1613    fn test_into_iter_full_consume() {
1614        let drop_count = Rc::new(RefCell::new(0));
1615
1616        let mut map = I64Map::new();
1617        map.insert(1, DropTracker::new(Rc::clone(&drop_count)));
1618        map.insert(2, DropTracker::new(Rc::clone(&drop_count)));
1619        map.insert(3, DropTracker::new(Rc::clone(&drop_count)));
1620
1621        // Fully consume the iterator
1622        for _ in map.into_iter() {}
1623
1624        // All 3 items should be dropped
1625        assert_eq!(*drop_count.borrow(), 3);
1626    }
1627
1628    #[test]
1629    fn test_drain_partial_consume_drops_remaining() {
1630        let drop_count = Rc::new(RefCell::new(0));
1631
1632        let mut map = I64Map::new();
1633        map.insert(1, DropTracker::new(Rc::clone(&drop_count)));
1634        map.insert(2, DropTracker::new(Rc::clone(&drop_count)));
1635        map.insert(3, DropTracker::new(Rc::clone(&drop_count)));
1636
1637        // Only consume one element from drain
1638        let mut drain = map.drain();
1639        let _ = drain.next();
1640
1641        assert_eq!(*drop_count.borrow(), 1);
1642
1643        // Drop drain
1644        drop(drain);
1645
1646        // All 3 should be dropped
1647        assert_eq!(*drop_count.borrow(), 3);
1648    }
1649
1650    #[test]
1651    fn test_basic_operations() {
1652        let mut map = I64Map::new();
1653
1654        assert!(map.insert(1, "one").is_none());
1655        assert!(map.insert(2, "two").is_none());
1656        assert!(map.insert(3, "three").is_none());
1657        assert_eq!(map.len(), 3);
1658
1659        assert_eq!(map.get(1), Some(&"one"));
1660        assert_eq!(map.get(2), Some(&"two"));
1661        assert_eq!(map.get(3), Some(&"three"));
1662        assert_eq!(map.get(4), None);
1663
1664        assert_eq!(map.insert(2, "TWO"), Some("two"));
1665        assert_eq!(map.get(2), Some(&"TWO"));
1666
1667        assert_eq!(map.remove(2), Some("TWO"));
1668        assert_eq!(map.get(2), None);
1669        assert_eq!(map.len(), 2);
1670    }
1671
1672    #[test]
1673    fn test_entry_api() {
1674        let mut map = I64Map::new();
1675
1676        *map.entry(1).or_insert(10) += 5;
1677        assert_eq!(map.get(1), Some(&15));
1678
1679        *map.entry(1).or_insert(100) += 5;
1680        assert_eq!(map.get(1), Some(&20));
1681
1682        map.entry(2).or_insert_with(|| 42);
1683        assert_eq!(map.get(2), Some(&42));
1684
1685        let v: &mut i32 = map.entry(3).or_default();
1686        *v = 99;
1687        assert_eq!(map.get(3), Some(&99));
1688    }
1689
1690    #[test]
1691    fn test_grow() {
1692        let mut map = I64Map::new();
1693
1694        for i in 0..1000 {
1695            map.insert(i, i * 2);
1696        }
1697
1698        assert_eq!(map.len(), 1000);
1699
1700        for i in 0..1000 {
1701            assert_eq!(map.get(i), Some(&(i * 2)));
1702        }
1703    }
1704
1705    #[test]
1706    fn test_edge_values() {
1707        let mut map = I64Map::new();
1708
1709        map.insert(i64::MIN, "min");
1710        map.insert(i64::MIN + 1, "near_min");
1711        map.insert(i64::MAX, "max");
1712        map.insert(0, "zero");
1713        map.insert(-1, "neg one");
1714        map.insert(1, "one");
1715
1716        assert_eq!(map.get(i64::MIN), Some(&"min"));
1717        assert_eq!(map.get(i64::MIN + 1), Some(&"near_min"));
1718        assert_eq!(map.get(i64::MAX), Some(&"max"));
1719        assert_eq!(map.get(0), Some(&"zero"));
1720        assert_eq!(map.get(-1), Some(&"neg one"));
1721        assert_eq!(map.get(1), Some(&"one"));
1722    }
1723
1724    #[test]
1725    fn test_deletion() {
1726        let mut map = I64Map::with_capacity(16);
1727
1728        for i in 0..10 {
1729            map.insert(i, i);
1730        }
1731
1732        map.remove(5);
1733        assert!(!map.contains_key(5));
1734
1735        for i in 0..10 {
1736            if i != 5 {
1737                assert_eq!(map.get(i), Some(&i));
1738            }
1739        }
1740
1741        map.insert(5, 55);
1742        assert_eq!(map.get(5), Some(&55));
1743    }
1744
1745    #[test]
1746    fn test_clear() {
1747        let mut map = I64Map::new();
1748
1749        for i in 0..100 {
1750            map.insert(i, i);
1751        }
1752
1753        map.clear();
1754        assert!(map.is_empty());
1755
1756        for i in 0..100 {
1757            assert!(!map.contains_key(i));
1758        }
1759    }
1760
1761    #[test]
1762    fn test_iterators() {
1763        let mut map = I64Map::new();
1764
1765        map.insert(1, 10);
1766        map.insert(2, 20);
1767        map.insert(3, 30);
1768
1769        let mut keys: Vec<_> = map.keys().collect();
1770        keys.sort();
1771        assert_eq!(keys, vec![1, 2, 3]);
1772
1773        let mut values: Vec<_> = map.values().copied().collect();
1774        values.sort();
1775        assert_eq!(values, vec![10, 20, 30]);
1776    }
1777
1778    #[test]
1779    fn test_drain() {
1780        let mut map = I64Map::new();
1781
1782        map.insert(1, 10);
1783        map.insert(2, 20);
1784        map.insert(3, 30);
1785
1786        let mut drained: Vec<_> = map.drain().collect();
1787        drained.sort_by_key(|(k, _)| *k);
1788
1789        assert_eq!(drained, vec![(1, 10), (2, 20), (3, 30)]);
1790        assert!(map.is_empty());
1791
1792        // Map should still be usable after drain
1793        map.insert(4, 40);
1794        assert_eq!(map.get(4), Some(&40));
1795    }
1796
1797    #[test]
1798    fn test_shrink_after_delete() {
1799        let mut map = I64Map::new();
1800
1801        // Insert many entries to grow the map
1802        for i in 0..1000 {
1803            map.insert(i, i * 2);
1804        }
1805
1806        let capacity_after_insert = map.capacity();
1807        assert!(capacity_after_insert >= 1000);
1808
1809        // Remove most entries (keep only 10)
1810        for i in 10..1000 {
1811            map.remove(i);
1812        }
1813
1814        assert_eq!(map.len(), 10);
1815
1816        // Capacity should have shrunk (automatic shrink after remove)
1817        let capacity_after_remove = map.capacity();
1818        assert!(
1819            capacity_after_remove < capacity_after_insert,
1820            "capacity should shrink: {} < {}",
1821            capacity_after_remove,
1822            capacity_after_insert
1823        );
1824
1825        // Verify remaining entries still work
1826        for i in 0..10 {
1827            assert_eq!(map.get(i), Some(&(i * 2)));
1828        }
1829    }
1830
1831    #[test]
1832    fn test_shrink_to_fit() {
1833        let mut map: I64Map<i64> = I64Map::with_capacity(1000);
1834
1835        // Insert only a few entries
1836        for i in 0..10 {
1837            map.insert(i, i);
1838        }
1839
1840        let initial_capacity = map.capacity();
1841        assert!(initial_capacity >= 1000);
1842
1843        // Shrink to fit
1844        map.shrink_to_fit();
1845
1846        let after_shrink = map.capacity();
1847        assert!(
1848            after_shrink < initial_capacity,
1849            "capacity should shrink: {} < {}",
1850            after_shrink,
1851            initial_capacity
1852        );
1853
1854        // Verify entries still work
1855        for i in 0..10 {
1856            assert_eq!(map.get(i), Some(&i));
1857        }
1858    }
1859
1860    #[test]
1861    fn test_strided_keys_no_collision_catastrophe() {
1862        // This test verifies that strided keys (e.g., multiples of 1024)
1863        // don't cause catastrophic collisions that would result in O(N^2) behavior.
1864        // With the old low-bit masking hash, this would timeout or be very slow.
1865        let mut map = I64Map::with_capacity(10000);
1866        let stride = 1024;
1867
1868        // Insert 10000 keys with stride of 1024
1869        for i in 0..10000i64 {
1870            map.insert(i * stride, i);
1871        }
1872
1873        // Verify all keys are present and correct
1874        assert_eq!(map.len(), 10000);
1875        for i in 0..10000i64 {
1876            assert_eq!(map.get(i * stride), Some(&i), "Missing key {}", i * stride);
1877        }
1878
1879        // Remove half and verify
1880        for i in (0..10000i64).step_by(2) {
1881            assert_eq!(map.remove(i * stride), Some(i));
1882        }
1883        assert_eq!(map.len(), 5000);
1884
1885        // Verify remaining half
1886        for i in (1..10000i64).step_by(2) {
1887            assert_eq!(map.get(i * stride), Some(&i));
1888        }
1889    }
1890
1891    #[test]
1892    fn test_i64_min_full_map_domain() {
1893        let mut map = I64Map::with_capacity(128);
1894        assert_eq!(map.insert(i64::MIN, 1), None);
1895        assert_eq!(map.insert(i64::MIN, 2), Some(1));
1896        *map.entry(i64::MIN)
1897            .and_modify(|value| *value += 1)
1898            .or_insert(0) += 1;
1899        assert_eq!(map.get(i64::MIN), Some(&4));
1900        assert_eq!(map.len(), 1);
1901
1902        for key in -64..=64 {
1903            map.insert(key, key);
1904        }
1905        map.reserve(1024);
1906        map.shrink_to_fit();
1907        assert_eq!(map.get(i64::MIN), Some(&4));
1908        assert!(map.keys().any(|key| key == i64::MIN));
1909        for (key, value) in map.iter_mut() {
1910            if key == i64::MIN {
1911                *value = 5;
1912            }
1913        }
1914
1915        let cloned = map.clone();
1916        assert_eq!(cloned.get(i64::MIN), Some(&5));
1917        let mut drained: Vec<_> = map.drain().collect();
1918        drained.sort_by_key(|(key, _)| *key);
1919        assert_eq!(drained.first(), Some(&(i64::MIN, 5)));
1920        assert!(map.is_empty());
1921
1922        let mut owned: Vec<_> = cloned.into_iter().collect();
1923        owned.sort_by_key(|(key, _)| *key);
1924        assert_eq!(owned.first(), Some(&(i64::MIN, 5)));
1925
1926        assert_eq!(map.entry(i64::MIN).or_insert(7), &7);
1927        assert_eq!(map.remove(i64::MIN), Some(7));
1928        assert_eq!(map.remove(i64::MIN), None);
1929    }
1930
1931    // =========================================================================
1932    // I64Set Tests
1933    // =========================================================================
1934
1935    #[test]
1936    fn test_i64set_basic_operations() {
1937        let mut set = I64Set::new();
1938
1939        assert!(set.insert(1));
1940        assert!(set.insert(2));
1941        assert!(set.insert(3));
1942        assert_eq!(set.len(), 3);
1943
1944        assert!(set.contains(1));
1945        assert!(set.contains(2));
1946        assert!(set.contains(3));
1947        assert!(!set.contains(4));
1948
1949        // Duplicate insert returns false
1950        assert!(!set.insert(2));
1951        assert_eq!(set.len(), 3);
1952
1953        // Remove
1954        assert!(set.remove(2));
1955        assert!(!set.contains(2));
1956        assert_eq!(set.len(), 2);
1957
1958        // Remove non-existent returns false
1959        assert!(!set.remove(2));
1960    }
1961
1962    #[test]
1963    fn test_i64set_grow() {
1964        let mut set = I64Set::new();
1965
1966        for i in 0..1000 {
1967            set.insert(i);
1968        }
1969
1970        assert_eq!(set.len(), 1000);
1971
1972        for i in 0..1000 {
1973            assert!(set.contains(i), "Missing key {}", i);
1974        }
1975    }
1976
1977    #[test]
1978    fn test_i64set_edge_values() {
1979        let mut set = I64Set::new();
1980
1981        set.insert(i64::MIN);
1982        set.insert(i64::MIN + 1);
1983        set.insert(i64::MAX);
1984        set.insert(0);
1985        set.insert(-1);
1986        set.insert(1);
1987
1988        assert!(set.contains(i64::MIN));
1989        assert!(set.contains(i64::MIN + 1));
1990        assert!(set.contains(i64::MAX));
1991        assert!(set.contains(0));
1992        assert!(set.contains(-1));
1993        assert!(set.contains(1));
1994    }
1995
1996    #[test]
1997    fn test_i64set_into_iter() {
1998        let mut set = I64Set::new();
1999        set.insert(1);
2000        set.insert(2);
2001        set.insert(3);
2002
2003        let mut values: Vec<i64> = set.into_iter().collect();
2004        values.sort();
2005        assert_eq!(values, vec![1, 2, 3]);
2006    }
2007
2008    #[test]
2009    fn test_i64set_partial_drain_finishes_on_drop() {
2010        let mut set = I64Set::new();
2011        set.insert(1);
2012        set.insert(2);
2013        set.insert(3);
2014
2015        {
2016            let mut drain = set.drain();
2017            assert!(drain.next().is_some());
2018        }
2019
2020        assert_eq!(set.len(), 0);
2021        assert_eq!(set.iter().count(), 0);
2022        assert!(set.insert(4));
2023        assert_eq!(set.iter().collect::<Vec<_>>(), vec![4]);
2024    }
2025
2026    #[test]
2027    fn test_i64set_from_iter() {
2028        let set: I64Set = vec![1, 2, 3, 2, 1].into_iter().collect();
2029        assert_eq!(set.len(), 3);
2030        assert!(set.contains(1));
2031        assert!(set.contains(2));
2032        assert!(set.contains(3));
2033    }
2034
2035    #[test]
2036    fn test_i64set_shrink_after_delete() {
2037        let mut set = I64Set::new();
2038
2039        // Insert many entries to grow the set
2040        for i in 0..1000 {
2041            set.insert(i);
2042        }
2043
2044        let capacity_after_insert = set.capacity();
2045        assert!(capacity_after_insert >= 1000);
2046
2047        // Remove most entries (keep only 10)
2048        for i in 10..1000 {
2049            set.remove(i);
2050        }
2051
2052        assert_eq!(set.len(), 10);
2053
2054        // Capacity should have shrunk (automatic shrink after remove)
2055        let capacity_after_remove = set.capacity();
2056        assert!(
2057            capacity_after_remove < capacity_after_insert,
2058            "capacity should shrink: {} < {}",
2059            capacity_after_remove,
2060            capacity_after_insert
2061        );
2062
2063        // Verify remaining entries still work
2064        for i in 0..10 {
2065            assert!(set.contains(i));
2066        }
2067    }
2068
2069    #[test]
2070    fn test_i64set_shrink_to_fit() {
2071        let mut set = I64Set::with_capacity(1000);
2072
2073        // Insert only a few entries
2074        for i in 0..10 {
2075            set.insert(i);
2076        }
2077
2078        let initial_capacity = set.capacity();
2079        assert!(initial_capacity >= 1000);
2080
2081        // Shrink to fit
2082        set.shrink_to_fit();
2083
2084        let after_shrink = set.capacity();
2085        assert!(
2086            after_shrink < initial_capacity,
2087            "capacity should shrink: {} < {}",
2088            after_shrink,
2089            initial_capacity
2090        );
2091
2092        // Verify entries still work
2093        for i in 0..10 {
2094            assert!(set.contains(i));
2095        }
2096    }
2097
2098    #[test]
2099    fn test_i64set_strided_keys() {
2100        let mut set = I64Set::with_capacity(10000);
2101        let stride = 1024;
2102
2103        for i in 0..10000i64 {
2104            set.insert(i * stride);
2105        }
2106
2107        assert_eq!(set.len(), 10000);
2108        for i in 0..10000i64 {
2109            assert!(set.contains(i * stride), "Missing key {}", i * stride);
2110        }
2111    }
2112
2113    #[test]
2114    fn test_i64set_min_full_domain() {
2115        let mut set = I64Set::with_capacity(128);
2116        assert!(set.insert(i64::MIN));
2117        assert!(!set.insert(i64::MIN));
2118        for key in -64..=64 {
2119            set.insert(key);
2120        }
2121        set.reserve(1024);
2122        set.shrink_to_fit();
2123        assert!(set.contains(i64::MIN));
2124        assert!(set.iter().any(|key| key == i64::MIN));
2125
2126        let cloned = set.clone();
2127        let mut drained: Vec<_> = set.drain().collect();
2128        drained.sort_unstable();
2129        assert_eq!(drained.first(), Some(&i64::MIN));
2130        assert!(set.is_empty());
2131
2132        let mut owned: Vec<_> = cloned.into_iter().collect();
2133        owned.sort_unstable();
2134        assert_eq!(owned.first(), Some(&i64::MIN));
2135
2136        assert!(set.insert(i64::MIN));
2137        assert!(set.remove(i64::MIN));
2138        assert!(!set.remove(i64::MIN));
2139    }
2140}