use core::borrow::Borrow;
use kevy_hash::KevyHash;
use crate::map::KevyMap;
impl<K, V> KevyMap<K, V> {
#[inline]
#[must_use]
pub fn find_slot<Q>(&self, key: &Q) -> Option<usize>
where
K: Borrow<Q>,
Q: KevyHash + Eq + ?Sized,
{
self.find_by_borrow(key)
}
#[inline]
#[must_use]
pub fn slot(&self, slot: usize) -> Option<(&K, &V)> {
if !self.slot_is_full(slot) {
return None;
}
let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_ref() };
Some((&kv.0, &kv.1))
}
#[inline]
#[must_use]
pub fn slot_mut(&mut self, slot: usize) -> Option<(&K, &mut V)> {
if !self.slot_is_full(slot) {
return None;
}
let kv = unsafe { (*self.slots_ptr.as_ptr().add(slot)).assume_init_mut() };
Some((&kv.0, &mut kv.1))
}
#[inline]
fn slot_is_full(&self, slot: usize) -> bool {
slot < self.cap && unsafe { *self.metadata_ptr.as_ptr().add(slot) } & 0x80 == 0
}
}
#[cfg(test)]
mod tests {
use crate::KevyMap;
#[test]
fn a_slot_follows_its_entry_until_the_table_changes_shape() {
let mut m: KevyMap<u64, u64> = KevyMap::new();
assert_eq!(m.slot(0), None, "an unallocated table has no slots");
for k in 0..crate::scaled(1000) as u64 {
m.insert(k, k * 2);
}
for k in 0..crate::scaled(1000) as u64 {
let s = m.find_slot(&k).expect("present");
assert_eq!(m.slot(s), Some((&k, &(k * 2))));
*m.slot_mut(s).expect("full").1 += 1;
assert_eq!(m.get(&k), Some(&(k * 2 + 1)));
}
let s = m.find_slot(&5).expect("present");
m.remove(&5);
assert_eq!(m.slot(s), None);
assert!(m.slot_mut(s).is_none());
let full = (0..m.capacity()).filter(|&i| m.slot(i).is_some()).count();
assert_eq!(full, m.len(), "exactly the occupied slots read as full");
}
}