use std::{cmp::Ordering, marker::PhantomData};
use crate::{
types::{
data::{Index, Val},
header::SlotType,
traits::{IDecode, IKey, IKeyCodec, ILoader},
},
utils::raw_ptr_to_ref,
};
use super::header::BaseHeader;
#[derive(Clone, Copy)]
pub(crate) struct Sst<K> {
data: *mut BaseHeader,
_marker: PhantomData<K>,
}
impl<K> Sst<K> {
pub(crate) fn new(data: *mut BaseHeader) -> Self {
debug_assert!(!data.is_null());
Self {
data,
_marker: PhantomData,
}
}
pub(crate) fn header(&self) -> &BaseHeader {
raw_ptr_to_ref(self.data)
}
fn data_at(&self, pos: usize) -> &[u8] {
let h = self.header();
unsafe {
let off = self.data.add(1).cast::<SlotType>().add(pos).read() as usize;
let p = self.data.cast::<u8>().add(off);
std::slice::from_raw_parts(p, h.size as usize - off)
}
}
}
impl<K> Sst<K>
where
K: Ord + IKeyCodec,
{
pub(crate) fn key_at(&self, pos: usize) -> K {
let raw = self.data_at(pos);
K::decode_from(raw)
}
pub(crate) fn search_by<F>(&self, key: &K, f: F) -> Result<usize, usize>
where
F: Fn(&K, &K) -> Ordering,
{
let h = self.header();
debug_assert!(h.elems > 0);
let rk = key.remove_prefix(h.prefix_len as usize);
let (mut lo, mut hi) = (0, h.elems as usize);
while lo < hi {
let mid = lo + ((hi - lo) >> 1);
let k = self.key_at(mid);
match f(&k, &rk) {
Ordering::Equal => return Ok(mid),
Ordering::Greater => hi = mid,
Ordering::Less => lo = mid + 1,
}
}
Err(lo)
}
pub(crate) fn lower_bound(&self, k: &K) -> Result<usize, usize> {
let h = self.header();
let elems = h.elems as usize;
let rk = k.remove_prefix(h.prefix_len as usize);
let (mut lo, mut hi) = (0, elems);
while lo < hi {
let mid = lo + ((hi - lo) >> 1);
let key = self.key_at(mid);
match key.cmp(&rk) {
Ordering::Less => lo = mid + 1,
_ => hi = mid,
}
}
if lo == elems { Err(lo) } else { Ok(lo) }
}
}
impl<K> Sst<K>
where
K: IKey,
{
pub fn kv_at<V: IDecode>(&self, pos: usize) -> (K, V) {
let raw = self.data_at(pos);
let k = K::decode_from(raw);
let v = V::decode_from(&raw[k.packed_size()..]);
(k, v)
}
pub(crate) fn show_intl(&self, pid: u64, addr: u64) {
let elems = self.header().elems as usize;
log::debug!("---------- show page {pid} {addr} elems {elems} ----------");
for i in 0..elems {
let (k, v) = self.kv_at::<Index>(i);
log::debug!("{} => {}", k.to_string(), v);
}
log::debug!("---------- end ----------");
}
pub(crate) fn show_leaf<L: ILoader>(&self, l: &L, pid: u64, addr: u64) {
let elems = self.header().elems as usize;
log::debug!("---------- show page {pid} {addr} elems {elems} ----------");
for i in 0..elems {
let (k, v) = self.kv_at::<Val>(i);
let (r, _) = v.get_record(l, true);
log::debug!("{} => {}", k.to_string(), r);
}
log::debug!("---------- end ----------");
}
}