use super::{inter::*, leaf::*};
use crate::{CACHE_LINE_SIZE, Various, trace_log};
use alloc::alloc::{Layout, alloc, handle_alloc_error};
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::ops::Bound;
use core::ptr::{self, NonNull};
pub(super) const AREA_SIZE: usize = 2 * CACHE_LINE_SIZE;
pub(super) const NODE_SIZE: usize = 2 * AREA_SIZE;
pub(super) const PTR_SIZE: usize = size_of::<*mut NodeHeader>();
pub(super) const PTR_ALIGN: usize = align_of::<*mut NodeHeader>();
#[repr(C)]
pub(super) struct NodeHeader {
pub height: u32,
pub count: u32,
}
impl NodeHeader {
#[inline]
pub unsafe fn get_field<T>(p: NonNull<Self>, offset: usize) -> *mut T {
unsafe { (p.as_ptr() as *const u8).add(offset) as *mut T }
}
#[inline(always)]
pub fn is_leaf(&self) -> bool {
self.height == 0
}
}
#[derive(Clone)]
pub(super) struct NodeBase {
pub header: NonNull<NodeHeader>,
}
impl NodeBase {
#[inline(always)]
pub fn _alloc(layout: Layout) -> Self {
unsafe {
let p: *mut u8 = alloc(layout);
if p.is_null() {
handle_alloc_error(layout);
}
let header = NonNull::new_unchecked(p as *mut NodeHeader);
Self { header }
}
}
#[inline(always)]
pub fn get_header(&self) -> &NodeHeader {
unsafe { self.header.as_ref() }
}
#[inline(always)]
pub fn get_header_mut(&mut self) -> &mut NodeHeader {
unsafe { self.header.as_mut() }
}
#[inline(always)]
pub fn get_ptr(&self) -> *mut NodeHeader {
self.header.as_ptr()
}
#[cfg(test)]
#[inline(always)]
pub fn get_array<T>(&self, header_size: usize, delta: usize) -> &[T] {
let header = self.get_header();
let items_ptr = unsafe { NodeHeader::get_field::<T>(self.header, header_size) };
unsafe { core::slice::from_raw_parts::<T>(items_ptr, header.count as usize + delta) }
}
#[inline(always)]
pub unsafe fn item_ptr<T>(&self, start_offset: usize, idx: u32) -> *mut T {
unsafe {
NodeHeader::get_field::<T>(self.header, start_offset + idx as usize * size_of::<T>())
}
}
#[inline(always)]
pub fn key_count(&self) -> u32 {
self.get_header().count
}
#[inline(always)]
pub fn height(&self) -> u32 {
self.get_header().height
}
#[inline]
pub fn _search<K, Q>(&self, header_offset: usize, key: &Q) -> (u32, bool)
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
macro_rules! _search {
($start: expr, $end: expr) => {
let mut idx = $start as u32;
if $start < $end {
let mut k = self.item_ptr::<K>(header_offset, $start as u32);
loop {
let k_ref: &K = &*k;
match k_ref.borrow().cmp(key) {
Ordering::Equal => return (idx, true),
Ordering::Greater => return (idx, false),
_ => {}
}
idx += 1;
k = k.add(1);
if idx == $end as u32 {
break;
}
}
}
return (idx, false);
};
}
unsafe {
let count = self.key_count();
let first_line_bytes = CACHE_LINE_SIZE - header_offset;
let first_line_limit = (first_line_bytes / size_of::<K>()) as u32;
if count > first_line_limit {
let first_line_last = &*self.item_ptr::<K>(header_offset, first_line_limit - 1);
if key > first_line_last.borrow() {
_search!(first_line_limit, count);
}
}
_search!(0, count);
}
}
#[inline(always)]
pub unsafe fn _insert<K, V>(
&mut self, key_header_offset: usize, value_header_offset: usize, idx: u32, key: K, value: V,
) -> *mut V {
let count = self.key_count();
unsafe {
let key_p = self.item_ptr::<K>(key_header_offset, idx);
if idx < count {
ptr::copy(key_p, key_p.add(1), (count - idx) as usize);
}
key_p.write(key);
let value_p = self.item_ptr::<V>(value_header_offset, idx);
if idx < count {
ptr::copy(value_p, value_p.add(1), (count - idx) as usize);
}
value_p.write(value);
self.get_header_mut().count = count + 1;
value_p
}
}
}
pub(crate) enum Node<K, V> {
Inter(InterNode<K, V>),
Leaf(LeafNode<K, V>),
}
impl<K, V> fmt::Debug for Node<K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Inter(node) => node.fmt(f),
Self::Leaf(node) => node.fmt(f),
}
}
}
impl<K: Ord, V> Clone for Node<K, V> {
#[inline(always)]
fn clone(&self) -> Self {
match self {
Self::Inter(node) => Self::Inter(node.clone()),
Self::Leaf(node) => Self::Leaf(node.clone()),
}
}
}
impl<K: Ord, V> Node<K, V> {
#[inline(always)]
pub unsafe fn from_header(header: *mut NodeHeader) -> Self {
unsafe {
if (*header).is_leaf() {
Self::Leaf(LeafNode::<K, V>::from_header(header))
} else {
Self::Inter(InterNode::<K, V>::from_header(header))
}
}
}
#[inline(always)]
pub fn is_leaf(&self) -> bool {
match self {
Self::Inter(_) => false,
Self::Leaf(_) => true,
}
}
#[inline(always)]
pub fn height(&self) -> u32 {
match self {
Self::Inter(node) => node.height(),
Self::Leaf(_) => 0,
}
}
#[cfg(test)]
pub fn as_inter(&self) -> &InterNode<K, V> {
if let Self::Inter(node) = &self {
node
} else {
unreachable!();
}
}
#[inline]
pub fn into_leaf(self) -> LeafNode<K, V> {
if let Self::Leaf(node) = self {
node
} else {
unreachable!();
}
}
#[inline]
pub fn find_leaf<Q>(&self, key: &Q) -> LeafNode<K, V>
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
match self {
Self::Leaf(node) => node.clone(),
Self::Inter(node) => {
let mut cur = node.clone();
loop {
let idx = cur.search_child(key);
trace_log!("find_leaf {cur:?} {idx}");
match cur.get_child(idx) {
Node::Leaf(leaf) => return leaf,
Node::Inter(inter) => {
cur = inter;
}
}
}
}
}
}
#[inline]
pub fn find_leaf_with_cache<Q>(&self, cache: &mut PathCache<K, V>, key: &Q) -> LeafNode<K, V>
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
match &self {
Self::Leaf(node) => node.clone(),
Self::Inter(node) => {
let mut cur = node.clone();
loop {
let idx = cur.search_child(key);
trace_log!("find_leaf_with_cache {cur:?} {idx}");
cache.push(cur.clone(), idx);
match cur.get_child(idx) {
Node::Leaf(leaf) => {
trace_log!("find_leaf_with_cache got {leaf:?}");
return leaf;
}
Node::Inter(inter) => {
cur = inter;
}
}
}
}
}
}
#[inline]
pub fn find_leaf_with_bound<Q>(&self, bound: Bound<&Q>, is_start: bool) -> (LeafNode<K, V>, u32)
where
K: Borrow<Q>,
Q: Ord + ?Sized,
{
let key = borrow_key_from_bound::<Q>(bound);
let mut cur = self.clone();
loop {
match cur {
Self::Leaf(node) => {
let idx = if let Some(k) = key.as_ref() {
let (idx, is_equal) = node.search(k);
if is_start {
if let Bound::Excluded(_) = bound {
if is_equal { idx + 1 } else { idx }
} else {
idx
}
} else {
if let Bound::Excluded(_) = bound {
idx
} else {
if is_equal { idx + 1 } else { idx }
}
}
} else {
if is_start { 0 } else { node.key_count() }
};
return (node, idx);
}
Self::Inter(node) => {
let idx = if let Some(k) = key.as_ref() {
node.search_child(k)
} else {
if is_start { 0 } else { node.key_count() - 1 }
};
cur = node.get_child(idx);
}
}
}
}
#[inline]
pub fn find_first_leaf(&self, mut cache: Option<&mut PathCache<K, V>>) -> LeafNode<K, V> {
let mut cur: Self = self.clone();
loop {
match cur {
Self::Leaf(leaf) => return leaf,
Self::Inter(inter) => {
if let Some(_cache) = cache.as_mut() {
_cache.push(inter.clone(), 0);
}
cur = inter.get_child(0);
}
}
}
}
#[inline]
pub fn find_last_leaf(&self, mut cache: Option<&mut PathCache<K, V>>) -> LeafNode<K, V> {
let mut cur: Self = self.clone();
loop {
match cur {
Self::Leaf(leaf) => return leaf,
Self::Inter(inter) => {
let idx = inter.key_count();
if let Some(_cache) = cache.as_mut() {
_cache.push(inter.clone(), idx);
}
cur = inter.get_child(idx);
}
}
}
}
}
macro_rules! _move_to_ancenstor {
($queue: expr, $cond: expr, $post: expr) => {{
let mut res = None;
while let Some((grand_parent, idx)) = $queue.pop() {
if $cond(&grand_parent, idx) {
res.replace((grand_parent, idx));
break;
} else {
($post)(grand_parent);
}
}
res
}};
}
pub(super) struct PathCache<K, V> {
pos: isize,
inner: Various<(InterNode<K, V>, u32)>,
}
impl<K: Ord, V> PathCache<K, V> {
#[inline]
pub fn new() -> Self {
Self { inner: Various::new(), pos: 0 }
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear();
self.pos = 0;
}
#[inline(always)]
pub fn take(&mut self) -> Self {
let mut inner = self.inner.take();
inner.clear();
Self { inner, pos: 0 }
}
#[inline(always)]
pub fn assert_center(&self) {
debug_assert_eq!(self.pos, 0);
}
#[inline]
fn _move_left_and_pop<F>(&mut self, post_callback: F) -> Option<(InterNode<K, V>, u32)>
where
F: Fn(InterNode<K, V>),
{
while let Some((parent, idx)) = self.inner.pop() {
debug_assert!(self.pos < 0);
let move_step = (-self.pos) as u32;
if idx > 0 {
if move_step > idx {
self.pos += idx as isize;
} else {
debug_assert_eq!(self.pos, 0);
self.pos += move_step as isize;
return Some((parent, idx - move_step)); }
}
let pre_height = parent.height();
post_callback(parent);
self.pos += 1;
let cond = |_node: &InterNode<K, V>, idx: u32| -> bool { idx > 0 };
let (grand_parent, grand_idx) =
_move_to_ancenstor!(self.inner, cond, post_callback).unwrap();
let (parent, idx) =
grand_parent.find_child_branch(pre_height, grand_idx - 1, false, Some(self));
if self.pos == 0 {
return Some((parent, idx));
} else {
self.inner.push((parent, idx));
}
}
None
}
#[inline]
fn _move_right_and_pop<F>(&mut self, post_callback: F) -> Option<(InterNode<K, V>, u32)>
where
F: Fn(InterNode<K, V>),
{
while let Some((parent, idx)) = self.inner.pop() {
debug_assert!(self.pos > 0);
let move_step = self.pos as u32;
let right_count = parent.key_count() - idx;
if right_count > 0 {
if right_count < move_step {
self.pos -= right_count as isize;
} else {
self.pos -= move_step as isize;
debug_assert_eq!(self.pos, 0);
return Some((parent, idx + move_step)); }
}
let pre_height = parent.height();
post_callback(parent);
self.pos -= 1;
if let Some((grand_parent, grand_idx)) = _move_to_ancenstor!(
self.inner,
|node: &InterNode<K, V>, idx: u32| -> bool { node.key_count() > idx },
post_callback
) {
let (parent, idx) =
grand_parent.find_child_branch(pre_height, grand_idx + 1, true, Some(self));
if self.pos == 0 {
return Some((parent, idx));
} else {
self.inner.push((parent, idx));
}
} else {
return None;
}
}
None
}
#[inline(always)]
pub fn peak_next(&self) -> Option<(InterNode<K, V>, u32)> {
debug_assert_eq!(self.pos, 0);
let (parent, idx) = self.inner.last()?;
Some((parent.clone(), *idx))
}
#[inline(always)]
pub fn peak_ancenstor<FC>(&mut self, cond: FC) -> Option<(InterNode<K, V>, u32)>
where
FC: Fn(&InterNode<K, V>, u32) -> bool,
{
let iter = self.inner.iter_rev();
for (grand_parent, idx) in iter {
if cond(grand_parent, *idx) {
return Some((grand_parent.clone(), *idx));
}
}
None
}
#[inline(always)]
pub fn move_to_ancenstor<FC, FP>(
&mut self, cond: FC, post_callback: FP,
) -> Option<(InterNode<K, V>, u32)>
where
FC: Fn(&InterNode<K, V>, u32) -> bool,
FP: Fn(InterNode<K, V>),
{
_move_to_ancenstor!(self, cond, post_callback)
}
#[inline(always)]
pub fn move_left(&mut self) {
self.pos -= 1;
}
#[inline(always)]
pub fn move_right(&mut self) {
self.pos += 1;
}
#[inline(always)]
pub fn push(&mut self, inter: InterNode<K, V>, idx: u32) {
self.inner.push((inter, idx));
}
#[inline(always)]
pub fn pop(&mut self) -> Option<(InterNode<K, V>, u32)> {
if self.pos < 0 {
self._move_left_and_pop(dummy_post_callback::<K, V>)
} else if self.pos > 0 {
self._move_right_and_pop(dummy_post_callback::<K, V>)
} else {
self.inner.pop()
}
}
#[inline(always)]
pub fn move_right_and_pop_l1<F>(&mut self, post_callback: F) -> Option<(InterNode<K, V>, u32)>
where
F: Fn(InterNode<K, V>) + Clone,
{
self.pos += 1;
self._move_right_and_pop(post_callback)
}
#[inline(always)]
pub fn move_left_and_pop_l1<F>(&mut self, post_callback: F) -> Option<(InterNode<K, V>, u32)>
where
F: Fn(InterNode<K, V>) + Clone,
{
self.pos -= 1;
self._move_left_and_pop(post_callback)
}
}
pub(super) fn dummy_post_callback<K, V>(_node: InterNode<K, V>) {}
#[inline(always)]
pub(super) fn borrow_key_from_bound<Q: ?Sized>(bound: Bound<&Q>) -> Option<&Q> {
match bound {
Bound::Unbounded => None,
Bound::Included(key) => Some(key),
Bound::Excluded(key) => Some(key),
}
}