type SplitResult<K, V> = Option<(K, V, Box<Node<K, V>>)>;
#[derive(Debug, PartialEq)]
struct Node<K, V> {
keys: Vec<K>,
values: Vec<V>,
children: Vec<Node<K, V>>,
is_leaf: bool,
}
impl<K: Ord + Clone, V: Clone> Node<K, V> {
fn new(is_leaf: bool) -> Self {
Node {
keys: Vec::new(),
values: Vec::new(),
children: Vec::new(),
is_leaf,
}
}
fn search(&self, key: &K) -> Option<&V> {
match self.keys.binary_search(key) {
Ok(i) => Some(&self.values[i]),
Err(i) => {
if self.is_leaf {
None
} else {
self.children[i].search(key)
}
}
}
}
fn insert(&mut self, key: K, value: V) -> SplitResult<K, V> {
let pos = self.keys.binary_search(&key).unwrap_or_else(|i| i);
if self.is_leaf {
self.keys.insert(pos, key);
self.values.insert(pos, value);
} else if let Some((split_key, split_val, split_child)) =
self.children[pos].insert(key, value)
{
self.keys.insert(pos, split_key);
self.values.insert(pos, split_val);
self.children.insert(pos + 1, *split_child);
}
let threshold = (self.keys.len() as f64).sqrt().ceil() as usize;
if self.keys.len() > threshold * 2 {
self.split()
} else {
None
}
}
fn split(&mut self) -> SplitResult<K, V> {
let mid = self.keys.len() / 2;
let mut new_node = Node::new(self.is_leaf);
new_node.keys = self.keys.split_off(mid + 1);
new_node.values = self.values.split_off(mid + 1);
if !self.is_leaf {
new_node.children = self.children.split_off(mid + 1);
}
let split_key = self.keys.pop().unwrap();
let split_value = self.values.pop().unwrap();
Some((split_key, split_value, Box::new(new_node)))
}
}
#[derive(Debug, PartialEq)]
pub struct CacheObliviousBTree<K, V> {
root: Box<Node<K, V>>,
size: usize,
}
impl<K: Ord + Clone, V: Clone> CacheObliviousBTree<K, V> {
pub fn new() -> Self {
CacheObliviousBTree {
root: Box::new(Node::new(true)),
size: 0,
}
}
pub fn insert(&mut self, key: K, value: V) {
if let Some((split_key, split_val, split_child)) = self.root.insert(key, value) {
let new_root = Node::new(false);
let old_root = std::mem::replace(&mut self.root, Box::new(new_root));
self.root.keys.push(split_key);
self.root.values.push(split_val);
self.root.children.push(*old_root);
self.root.children.push(*split_child);
}
self.size += 1;
}
pub fn search(&self, key: &K) -> Option<&V> {
self.root.search(key)
}
pub fn len(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
}
impl<K: Ord + Clone, V: Clone> Default for CacheObliviousBTree<K, V> {
fn default() -> Self {
Self::new()
}
}