use super::merge::ColPtr;
use crate::schema::key::{pk_width_dispatch, PkSortKey};
use gnitz_wire::RowSource;
#[inline]
fn lower_bound_by(mut lo: usize, mut hi: usize, lt: impl Fn(usize) -> bool) -> usize {
while lo < hi {
let mid = lo + (hi - lo) / 2;
if lt(mid) {
lo = mid + 1;
} else {
hi = mid;
}
}
lo
}
#[inline]
pub(crate) fn gallop_by(count: usize, hint: usize, lt: impl Fn(usize) -> bool) -> usize {
let h = hint.min(count);
if h < count && lt(h) {
let mut lo = h; let mut step = 1usize;
while lo + step < count && lt(lo + step) {
lo += step;
step *= 2;
}
let hi = (lo + step).min(count); return lower_bound_by(lo + 1, hi, lt);
}
if h == 0 || lt(h - 1) {
return h;
} lower_bound_by(0, h, lt) }
#[inline]
pub(crate) unsafe fn seek_lower_bound(count: usize, stride: usize, pk: ColPtr, key: &[u8]) -> usize {
debug_assert_eq!(key.len(), stride, "seek probe width must equal pk_stride");
pk_width_dispatch!(stride, |K| {
let p = K::from_opk(key);
lower_bound_by(0, count, |i| K::from_opk(pk.row(i, stride)) < p)
})
}
#[inline]
pub(crate) unsafe fn seek_advance_to(count: usize, stride: usize, pk: ColPtr, key: &[u8], hint: usize) -> usize {
debug_assert_eq!(key.len(), stride, "seek probe width must equal pk_stride");
pk_width_dispatch!(stride, |K| {
let p = K::from_opk(key);
gallop_by(count, hint, |i| K::from_opk(pk.row(i, stride)) < p)
})
}
#[inline]
pub fn pk_group_end<S: RowSource>(src: &S, start: usize) -> usize {
let k = src.get_pk_bytes(start);
let count = src.row_count();
let mut j = start + 1;
while j < count && crate::schema::key::pk_bytes_eq(src.get_pk_bytes(j), k) {
j += 1;
}
j
}
#[inline]
pub(crate) fn pk_prefix_group_end<S: RowSource>(src: &S, start: usize, width: usize) -> usize {
let k = &src.get_pk_bytes(start)[..width];
let count = src.row_count();
let mut j = start + 1;
while j < count && crate::schema::key::pk_bytes_eq(&src.get_pk_bytes(j)[..width], k) {
j += 1;
}
j
}
#[cfg(test)]
#[path = "tests/seek.rs"]
mod tests;
#[cfg(test)]
#[path = "benches/seek.rs"]
mod bench;