use crate::engine::hash::HashResult;
use crate::engine::slab::SlabPool;
#[derive(Clone, Copy)]
#[repr(C, packed)]
pub struct Slot {
pub data: [u8; 14],
}
impl Slot {
#[inline]
pub const fn empty() -> Self {
Self { data: [0u8; 14] }
}
#[inline]
pub fn clear(&mut self) {
self.data = [0u8; 14];
}
#[inline]
pub fn get_mode(&self) -> u8 {
(self.data[0] >> 7) & 1
}
#[inline]
pub fn set_inline(&mut self, key: &[u8], value: &[u8]) {
debug_assert!(key.len() <= 6 && value.len() <= 7);
self.data = [0u8; 14];
self.data[0] = ((key.len() as u8) << 4) | ((value.len() as u8 & 0x07) << 1);
self.data[1..1 + key.len()].copy_from_slice(key);
self.data[7..7 + value.len()].copy_from_slice(value);
}
#[inline]
fn inline_key_len(&self) -> usize {
((self.data[0] >> 4) & 0x07) as usize
}
#[inline]
pub fn inline_key(&self) -> &[u8] {
let len = self.inline_key_len();
&self.data[1..1 + len]
}
#[inline]
fn inline_val_len(&self) -> usize {
((self.data[0] >> 1) & 0x07) as usize
}
#[inline]
pub fn inline_value(&self) -> &[u8] {
let len = self.inline_val_len();
&self.data[7..7 + len]
}
#[inline]
pub fn set_slab(&mut self, ext_fp_hi: u8, ext_fp: u32, slab_idx: usize) {
self.data = [0u8; 14];
self.data[0] = 0x80 | (ext_fp_hi & 0x7F);
self.data[1..5].copy_from_slice(&ext_fp.to_le_bytes());
self.data[5] = 0;
self.data[6..14].copy_from_slice(&(slab_idx as u64).to_le_bytes());
}
#[inline]
pub fn slab_idx(&self) -> usize {
let mut bytes = [0u8; 8];
bytes.copy_from_slice(&self.data[6..14]);
u64::from_le_bytes(bytes) as usize
}
#[inline]
fn get_ext_fp(&self) -> u32 {
let mut bytes = [0u8; 4];
bytes.copy_from_slice(&self.data[1..5]);
u32::from_le_bytes(bytes)
}
#[inline]
fn get_ext_fp_hi(&self) -> u8 {
self.data[0] & 0x7F
}
#[inline]
pub fn slab_key<'a>(&self, pool: &'a SlabPool) -> &'a [u8] {
pool.get(self.slab_idx()).key()
}
#[inline(always)]
pub fn matches_key(&self, key: &[u8], hr: &HashResult, pool: &SlabPool) -> bool {
if self.get_mode() == 0 {
self.inline_key() == key
} else {
if self.get_ext_fp_hi() != hr.ext_fp_hi || self.get_ext_fp() != hr.ext_fp {
return false;
}
pool.get(self.slab_idx()).key() == key
}
}
#[inline(always)]
pub fn get_value<'s, 'p>(&'s self, pool: &'p SlabPool) -> &'p [u8]
where
's: 'p,
{
if self.get_mode() == 0 {
self.inline_value()
} else {
pool.get(self.slab_idx()).value()
}
}
#[inline]
pub fn get_key_bytes<'s, 'p>(&'s self, pool: &'p SlabPool) -> &'p [u8]
where
's: 'p,
{
if self.get_mode() == 0 {
self.inline_key()
} else {
pool.get(self.slab_idx()).key()
}
}
#[inline]
pub fn get_value_bytes<'s, 'p>(&'s self, pool: &'p SlabPool) -> &'p [u8]
where
's: 'p,
{
if self.get_mode() == 0 {
self.inline_value()
} else {
pool.get(self.slab_idx()).value()
}
}
}