use core::ops::Sub;
use super::node_dispatch::SmallNode;
use smallnum::SmallUnsigned;
use tinyvec::ArrayVec;
#[derive(Clone, Debug, Default)]
pub struct Node<K, V, U> {
key: K,
val: V,
left_idx: Option<U>,
right_idx: Option<U>,
#[cfg(feature = "fast_rebalance")]
subtree_size: U,
}
impl<K, V, U: SmallUnsigned> Node<K, V, U> {
pub fn new(key: K, val: V) -> Self {
Node {
key,
val,
left_idx: None,
right_idx: None,
#[cfg(feature = "fast_rebalance")]
subtree_size: U::checked_from(1),
}
}
}
impl<K: Default, V: Default, U: SmallUnsigned + Copy> SmallNode<K, V> for Node<K, V, U> {
fn key(&self) -> &K {
&self.key
}
fn set_key(&mut self, key: K) {
self.key = key;
}
fn take_key(&mut self) -> K {
core::mem::take(&mut self.key)
}
fn val(&self) -> &V {
&self.val
}
fn get_mut(&mut self) -> (&K, &mut V) {
(&self.key, &mut self.val)
}
fn take_val(&mut self) -> V {
core::mem::take(&mut self.val)
}
fn set_val(&mut self, val: V) {
self.val = val;
}
fn left_idx(&self) -> Option<usize> {
self.left_idx.map(|i| i.usize())
}
fn set_left_idx(&mut self, opt_idx: Option<usize>) {
match opt_idx {
Some(idx) => self.left_idx = Some(U::checked_from(idx)),
None => self.left_idx = None,
}
}
fn right_idx(&self) -> Option<usize> {
self.right_idx.map(|i| i.usize())
}
fn set_right_idx(&mut self, opt_idx: Option<usize>) {
match opt_idx {
Some(idx) => self.right_idx = Some(U::checked_from(idx)),
None => self.right_idx = None,
}
}
#[cfg(feature = "fast_rebalance")]
fn subtree_size(&self) -> usize {
self.subtree_size.usize()
}
#[cfg(feature = "fast_rebalance")]
fn set_subtree_size(&mut self, size: usize) {
self.subtree_size = U::checked_from(size);
}
}
#[derive(Debug, Default, PartialEq, Eq)]
pub struct NodeGetHelper<U> {
node_idx: Option<U>,
parent_idx: Option<U>,
is_right_child: bool,
}
impl<U: SmallUnsigned + Copy> NodeGetHelper<U> {
pub fn new(node_idx: Option<usize>, parent_idx: Option<usize>, is_right_child: bool) -> Self {
NodeGetHelper {
node_idx: node_idx.map(|i| U::checked_from(i)),
parent_idx: parent_idx.map(|i| U::checked_from(i)),
is_right_child,
}
}
pub fn node_idx(&self) -> Option<usize> {
self.node_idx.map(|i| i.usize())
}
pub fn parent_idx(&self) -> Option<usize> {
self.parent_idx.map(|i| i.usize())
}
pub fn is_right_child(&self) -> bool {
self.is_right_child
}
}
#[derive(Debug, Default, PartialEq, Eq)]
pub struct NodeRebuildHelper<U> {
pub low_idx: U,
pub high_idx: U,
pub mid_idx: U,
}
impl<U: SmallUnsigned + Ord + Sub + Copy> NodeRebuildHelper<U> {
pub fn new(low_idx: usize, high_idx: usize) -> Self {
debug_assert!(
high_idx >= low_idx,
"Node rebuild helper low/high index reversed!"
);
NodeRebuildHelper {
low_idx: U::checked_from(low_idx),
high_idx: U::checked_from(high_idx),
mid_idx: U::checked_from(low_idx + ((high_idx - low_idx) / 2)),
}
}
}
#[derive(Debug, Default)]
pub struct NodeSwapHistHelper<U: Default, const N: usize> {
history: ArrayVec<[(U, U); N]>,
}
impl<U: Ord + Default + Copy + SmallUnsigned, const N: usize> NodeSwapHistHelper<U, N> {
pub fn new() -> Self {
NodeSwapHistHelper {
history: ArrayVec::<[(U, U); N]>::default(),
}
}
pub fn add(&mut self, pos_1: usize, pos_2: usize) {
debug_assert_ne!(pos_1, pos_2);
let mut known_pos_1 = false;
let mut known_pos_2 = false;
let pos_1 = U::checked_from(pos_1);
let pos_2 = U::checked_from(pos_2);
for (_, curr_idx) in self.history.iter_mut() {
if *curr_idx == pos_1 {
*curr_idx = pos_2;
known_pos_1 = true;
} else if *curr_idx == pos_2 {
*curr_idx = pos_1;
known_pos_2 = true;
}
}
if !known_pos_1 {
self.history.push((pos_1, pos_2));
}
if !known_pos_2 {
self.history.push((pos_2, pos_1));
}
}
pub fn curr_idx(&self, orig_pos: usize) -> usize {
debug_assert!(
self.history
.iter()
.filter(|(k, _)| (*k).usize() == orig_pos)
.count()
<= 1
);
match self
.history
.iter()
.filter(|(k, _)| (*k).usize() == orig_pos)
.map(|(_, curr)| *curr)
.next()
{
Some(curr_idx) => curr_idx.usize(),
None => orig_pos,
}
}
}
#[cfg(not(feature = "low_mem_insert"))]
#[cfg(test)]
mod tests {
use super::Node;
use smallnum::small_unsigned;
use std::mem::size_of;
#[test]
fn test_node_sizing() {
#[cfg(target_pointer_width = "64")]
#[cfg(not(feature = "fast_rebalance"))]
{
assert_eq!(size_of::<Node<u32, u32, small_unsigned!(1024)>>(), 16);
}
#[cfg(target_pointer_width = "64")]
#[cfg(feature = "fast_rebalance")]
{
assert_eq!(size_of::<Node<u32, u32, small_unsigned!(1024)>>(), 20);
}
}
}