#![forbid(unsafe_code)]
use core::mem;
use super::node::inline_keys::SearchKey;
use super::node::leaf::Leaf;
use super::node::page::FreshPage;
use super::node::{Insertion, Node};
use super::node_stack::{MAX_DEPTH, NodeStackMut};
use super::prefix::PrefixedKey;
use super::root::Tree;
use crate::allocator::Allocator;
use crate::inline_key::InlineKeyStrategy;
impl<K, V, S: InlineKeyStrategy<K>> Tree<K, V, S> {
#[inline(always)]
pub(crate) fn insert(
&mut self,
key: K,
value: V,
alloc: &impl Allocator,
length: &mut usize,
) -> Option<V>
where
K: Ord,
{
let key = match self.rightmost_append(key) {
Ok(append) => {
append.insert(value);
*length += 1;
return None;
}
Err(key) => key,
};
let key = self.shrink_shared_prefix_for(key, alloc);
match self
.root_mut()
.search_for_insert(&SearchKey::new(key.key()))
{
Ok(found) => {
drop(key);
return Some(mem::replace(found.value_mut(), value));
}
Err((leaf, edge)) => {
if leaf.len() < Leaf::<K, V, S>::capacity() {
leaf.insert_fit(edge, key.window_at(leaf.prefix_len()), value);
*length += 1;
return None;
}
}
}
self.insert_with_stack(key, value, alloc, length)
}
#[inline(never)]
pub(in crate::tree) fn insert_with_stack(
&mut self,
key: PrefixedKey<K>,
value: V,
alloc: &impl Allocator,
length: &mut usize,
) -> Option<V>
where
K: Ord,
{
let mut stack = NodeStackMut::new(self);
if stack.search(&SearchKey::new(key.key())) {
drop(key);
Some(mem::replace(stack.value_mut(), value))
} else {
stack.insert_prefixed(key, value, alloc, length);
stack.finish_insertion();
None
}
}
}
impl<'a, K, V, S: InlineKeyStrategy<K>> NodeStackMut<'a, K, V, S> {
pub(crate) fn at_new_root(tree: &'a mut Tree<K, V, S>, alloc: &impl Allocator) -> Self {
debug_assert!(!tree.has_root(), "a new tree in place of one");
*tree = Tree::new(alloc);
let mut stack = Self::new(tree);
stack.start_at_root();
stack
}
#[inline]
pub(crate) fn insert(&mut self, key: K, value: V, alloc: &impl Allocator, length: &mut usize) {
let key = self.shrink_shared_prefix_for(key, alloc);
self.insert_prefixed(key, value, alloc, length);
}
#[inline]
pub(in crate::tree) fn insert_prefixed(
&mut self,
key: PrefixedKey<K>,
value: V,
alloc: &impl Allocator,
length: &mut usize,
) {
let index = self.index();
let leaf = self.leaf();
assert!(index <= leaf.len(), "edge index out of bounds");
let prefix_len = leaf.prefix_len();
if leaf.len() < Leaf::<K, V, S>::capacity() {
leaf.insert_fit(index, key.window_at(prefix_len), value);
*length += 1;
} else {
self.insert_splitting(key, value, alloc, length);
}
}
#[inline(never)]
fn insert_splitting(
&mut self,
key: PrefixedKey<K>,
value: V,
alloc: &impl Allocator,
length: &mut usize,
) {
let index = self.index();
let leaf = self.leaf();
let key = key.window_at(leaf.prefix_len());
let split = leaf.split_insert(index, key, value, FreshPage::allocate(alloc));
let mut indexes_in_halves = [0; MAX_DEPTH + 1];
indexes_in_halves[0] = split.inserted.index();
let mut separator_indexes = [0; MAX_DEPTH + 1];
let mut carried = (
split.separator,
Node::Leaf(split.right),
split.inserted.is_right(),
);
let mut climbed = 0;
let levels_climbed = loop {
let (separator, right, entry_is_right) = carried;
let node = self.ascend_raising(alloc);
climbed += 1;
let index = self.index();
let beside_separator =
|separator_index: usize| separator_index + usize::from(entry_is_right);
match node.insert(index, separator, right, alloc) {
Insertion::Fit(separator_index) => {
separator_indexes[climbed] = separator_index;
self.set_index(beside_separator(separator_index));
break climbed;
}
Insertion::Split(split) => {
separator_indexes[climbed] = split.inserted.index();
indexes_in_halves[climbed] = beside_separator(split.inserted.index());
carried = (
split.separator,
Node::Internal(split.right),
split.inserted.is_right(),
);
}
}
};
for climbed in (0..levels_climbed).rev() {
self.descend();
self.set_index(indexes_in_halves[climbed]);
}
*length += 1;
self.refit_split_halves(&separator_indexes, levels_climbed);
}
}