use std::hash::{BuildHasher, Hasher};
use super::entry::KvValue;
use super::slab::SlabAllocator;
#[derive(Clone)]
struct FxBuildHasher;
impl BuildHasher for FxBuildHasher {
type Hasher = FxHasher;
fn build_hasher(&self) -> FxHasher {
FxHasher { hash: 0 }
}
}
struct FxHasher {
hash: u64,
}
const FX_SEED: u64 = 0x517c_c1b7_2722_0a95;
impl Hasher for FxHasher {
fn finish(&self) -> u64 {
self.hash
}
fn write(&mut self, bytes: &[u8]) {
for &b in bytes {
self.hash = self.hash.rotate_left(5) ^ (b as u64).wrapping_mul(FX_SEED);
}
}
}
pub(super) fn hash_key(key: &[u8]) -> u64 {
let hasher_builder = FxBuildHasher;
let mut h = hasher_builder.build_hasher();
h.write(key);
h.finish()
}
pub(super) fn fxhash_multi(slices: &[&[u8]]) -> u64 {
let mut h: u64 = 0;
for slice in slices {
for &b in *slice {
h = h.rotate_left(5) ^ (b as u64).wrapping_mul(FX_SEED);
}
}
h
}
use super::entry::KvEntry;
pub(super) fn read_value_from<'a>(entry: &'a KvEntry, overflow: &'a SlabAllocator) -> &'a [u8] {
match &entry.value {
KvValue::Inline(data) => data,
KvValue::Overflow { index, len } => overflow.get(*index, *len),
}
}
pub(super) fn extract_value_from(value: &KvValue, overflow: &SlabAllocator) -> Vec<u8> {
match value {
KvValue::Inline(data) => data.clone(),
KvValue::Overflow { index, len } => overflow.get(*index, *len).to_vec(),
}
}
pub(super) fn store_value_in(
overflow: &mut SlabAllocator,
value: &[u8],
inline_threshold: usize,
) -> KvValue {
if value.len() <= inline_threshold {
KvValue::Inline(value.to_vec())
} else {
let (index, len) = overflow.alloc(value);
KvValue::Overflow { index, len }
}
}
pub(super) fn free_value_from(value: &KvValue, overflow: &mut SlabAllocator) {
if let KvValue::Overflow { index, len } = value {
overflow.free(*index, *len);
}
}