use std::cmp::Ordering;
use seize::LocalGuard;
use crate::leaf_trait::TreeLeafNode;
use crate::leaf15::LeafNode15;
use crate::leaf15::{KSUF_KEYLENX, LAYER_KEYLENX};
use crate::policy::LeafPolicy;
use super::cursor_key::CursorKey;
#[derive(Debug, Clone, Copy)]
pub struct KeyIndexedPosition {
pub i: usize,
pub p: Option<usize>,
}
impl KeyIndexedPosition {
#[inline(always)]
pub const fn not_found(i: usize) -> Self {
Self { i, p: None }
}
#[inline(always)]
pub const fn found(i: usize, slot: usize) -> Self {
Self { i, p: Some(slot) }
}
}
#[inline(always)]
pub const fn initial_ksuf_match(ksuf_compare: Ordering, emit_equal: bool) -> bool {
match ksuf_compare {
Ordering::Greater => true,
Ordering::Equal => emit_equal,
Ordering::Less => false,
}
}
#[inline]
pub fn lower_with_position<P>(
cursor_key: &CursorKey,
leaf: &LeafNode15<P>,
perm: &<LeafNode15<P> as TreeLeafNode<P>>::Perm,
) -> KeyIndexedPosition
where
P: LeafPolicy,
{
let size: usize = perm.size();
let search_ikey: u64 = cursor_key.current_ikey();
for i in 0..size {
let slot: usize = perm.get(i);
let slot_ikey: u64 = leaf.ikey_relaxed(slot);
match search_ikey.cmp(&slot_ikey) {
Ordering::Less => {
return KeyIndexedPosition::not_found(i);
}
Ordering::Equal => {
return KeyIndexedPosition::found(i, slot);
}
Ordering::Greater => {
}
}
}
KeyIndexedPosition::not_found(size)
}
#[inline]
pub fn lower_with_suffix<P>(
cursor_key: &CursorKey,
leaf: &LeafNode15<P>,
perm: &<LeafNode15<P> as TreeLeafNode<P>>::Perm,
) -> usize
where
P: LeafPolicy,
{
let base_pos: KeyIndexedPosition = lower_with_position(cursor_key, leaf, perm);
let Some(slot) = base_pos.p else {
return base_pos.i;
};
let keylenx: u8 = leaf.keylenx_relaxed(slot);
if keylenx >= LAYER_KEYLENX {
if cursor_key.has_suffix() {
return base_pos.i + 1;
}
return base_pos.i;
}
if !cursor_key.has_suffix() {
let cursor_len = cursor_key.current_len();
let slot_len = keylenx as usize;
return match cursor_len.cmp(&slot_len) {
Ordering::Less => base_pos.i, Ordering::Equal => {
base_pos.i + 1
}
Ordering::Greater => {
find_position_after_inline(cursor_key, leaf, perm, base_pos.i)
}
};
}
if keylenx == KSUF_KEYLENX
&& let Some(stored_suffix) = leaf.ksuf(slot)
{
let cursor_suffix: &[u8] = cursor_key.suffix();
match cursor_suffix.cmp(stored_suffix) {
Ordering::Less => {
return base_pos.i;
}
Ordering::Equal => {
return base_pos.i + 1;
}
Ordering::Greater => {
return find_position_after_suffix(cursor_key, leaf, perm, base_pos.i);
}
}
}
find_position_after_suffix(cursor_key, leaf, perm, base_pos.i)
}
#[cold]
#[inline(never)]
fn find_position_after_inline<P>(
cursor_key: &CursorKey,
leaf: &LeafNode15<P>,
perm: &<LeafNode15<P> as TreeLeafNode<P>>::Perm,
start_i: usize,
) -> usize
where
P: LeafPolicy,
{
let size: usize = perm.size();
let search_ikey: u64 = cursor_key.current_ikey();
let cursor_len: usize = cursor_key.current_len();
for i in (start_i + 1)..size {
let slot: usize = perm.get(i);
let slot_ikey: u64 = leaf.ikey_relaxed(slot);
if slot_ikey != search_ikey {
return i;
}
let keylenx: u8 = leaf.keylenx_relaxed(slot);
if keylenx == KSUF_KEYLENX || keylenx >= LAYER_KEYLENX {
return i;
}
if cursor_len <= keylenx as usize {
return i;
}
}
size
}
#[cold]
#[inline(never)]
fn find_position_after_suffix<P>(
cursor_key: &CursorKey,
leaf: &LeafNode15<P>,
perm: &<LeafNode15<P> as TreeLeafNode<P>>::Perm,
start_i: usize,
) -> usize
where
P: LeafPolicy,
{
let size: usize = perm.size();
let search_ikey: u64 = cursor_key.current_ikey();
for i in (start_i + 1)..size {
let slot: usize = perm.get(i);
let slot_ikey: u64 = leaf.ikey_relaxed(slot);
if slot_ikey != search_ikey {
return i;
}
let keylenx: u8 = leaf.keylenx_relaxed(slot);
if keylenx == KSUF_KEYLENX
&& let Some(stored_suffix) = leaf.ksuf(slot)
&& cursor_key.suffix() <= stored_suffix
{
return i;
}
}
size
}
#[derive(Clone, Copy, Debug)]
pub struct ReverseScanHelper;
impl ReverseScanHelper {
#[inline(always)]
pub const fn prev(ki: isize) -> isize {
ki - 1
}
#[inline(always)]
pub fn retreat<P>(leaf: &LeafNode15<P>) -> *mut LeafNode15<P>
where
P: LeafPolicy,
{
unsafe { leaf.prev_unguarded() }
}
pub fn stable_reverse<P>(
leaf: &mut *mut LeafNode15<P>,
cursor_key: &CursorKey,
guard: &LocalGuard<'_>,
) -> u32
where
P: LeafPolicy,
{
loop {
let current: &LeafNode15<P> = unsafe { &**leaf };
let v: u32 = current.version().stable();
let next_ptr: *mut LeafNode15<P> = current.safe_next(guard);
if next_ptr.is_null() {
return v;
}
let next_bound_ikey: u64 = unsafe { &*next_ptr }.ikey_bound();
match cursor_key.current_ikey().cmp(&next_bound_ikey) {
Ordering::Less => return v,
Ordering::Equal if cursor_key.current_len() == 0 => {
return v;
}
_ => {
*leaf = next_ptr;
}
}
}
}
#[inline(always)]
pub const fn initial_ksuf_match_reverse(ksuf_compare: Ordering, emit_equal: bool) -> bool {
match ksuf_compare {
Ordering::Less => true,
Ordering::Equal => emit_equal,
Ordering::Greater => false,
}
}
#[inline(always)]
pub fn is_duplicate_reverse(
cursor_key: &CursorKey,
ikey: u64,
keylenx: u8,
upper_bound: bool,
) -> bool {
if upper_bound {
return false;
}
cursor_key.compare(ikey, keylenx as usize) != Ordering::Greater
}
#[inline]
pub fn lower_reverse<P>(
cursor_key: &CursorKey,
leaf: &LeafNode15<P>,
perm: &<LeafNode15<P> as TreeLeafNode<P>>::Perm,
upper_bound: bool,
) -> isize
where
P: LeafPolicy,
{
if upper_bound {
return perm.size().cast_signed() - 1;
}
let kx: KeyIndexedPosition = lower_with_position(cursor_key, leaf, perm);
if kx.p.is_some() {
kx.i.cast_signed()
} else {
kx.i.cast_signed() - 1
}
}
}
#[cfg(test)]
mod unit_tests;