use super::super::bitmap::{ArrayIndex, SmallBitmap};
use super::super::hash::{HashedKey, LevelIndex};
use super::super::helper;
use super::super::operation::*;
use super::super::sharedref::SharedRef;
use std::borrow::Borrow;
use std::error::Error;
use std::fmt::Debug;
use std::slice;
#[derive(Clone, Debug)]
pub struct Node<K, V> {
pub bitmap: SmallBitmap,
pub children: Box<[SharedRef<Entry<K, V>>]>,
}
pub type NodeIter<'a, K, V> = slice::Iter<'a, SharedRef<Entry<K, V>>>;
#[derive(Debug)]
pub struct Collision<K, V>(Box<[(K, V)]>);
impl<K, V> Collision<K, V> {
pub fn from_vec(vec: Vec<(K, V)>) -> Self {
assert!(vec.len() >= 2);
Collision(vec.into())
}
pub fn from_box(b: Box<[(K, V)]>) -> Self {
assert!(b.len() >= 2);
Collision(b)
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn iter(&self) -> slice::Iter<'_, (K, V)> {
self.0.iter()
}
}
impl<K: Clone + PartialEq, V: Clone> Collision<K, V> {
pub fn insert(&self, k: K, v: V) -> Result<Self, InsertError> {
if self.0.iter().any(|(lk, _)| lk == &k) {
Err(InsertError::EntryExists)
} else {
Ok(Collision::from_box(helper::clone_array_and_extend(
&self.0,
(k, v),
)))
}
}
fn get_record_and_pos<Q>(&self, k: &Q) -> Option<(usize, &(K, V))>
where
K: Borrow<Q>,
Q: PartialEq,
{
self.0
.iter()
.enumerate()
.find(|(_, (fk, _))| fk.borrow() == k)
}
pub fn remove<Q>(&self, h: HashedKey, k: &Q) -> Result<Entry<K, V>, RemoveError>
where
K: Borrow<Q>,
Q: PartialEq,
{
let (pos, _) = self.get_record_and_pos(k).ok_or(RemoveError::KeyNotFound)?;
if self.0.len() == 2 {
let to_keep = if pos == 0 { &self.0[1] } else { &self.0[0] };
Ok(Entry::Leaf(h, to_keep.0.clone(), to_keep.1.clone()))
} else {
let col = Collision::from_box(helper::clone_array_and_remove_at_pos(&self.0, pos));
Ok(Entry::LeafMany(h, col))
}
}
pub fn remove_match<Q>(&self, h: HashedKey, k: &Q, v: &V) -> Result<Entry<K, V>, RemoveError>
where
K: Borrow<Q>,
Q: PartialEq,
V: PartialEq,
{
let (pos, _) = self.get_record_and_pos(k).ok_or(RemoveError::KeyNotFound)?;
if &self.0[pos].1 != v {
Err(RemoveError::ValueNotMatching)
} else if self.0.len() == 2 {
let to_keep = if pos == 0 { &self.0[1] } else { &self.0[0] };
Ok(Entry::Leaf(h, to_keep.0.clone(), to_keep.1.clone()))
} else {
let col = Collision::from_box(helper::clone_array_and_remove_at_pos(&self.0, pos));
Ok(Entry::LeafMany(h, col))
}
}
pub fn update<F, U>(&self, h: HashedKey, k: &K, f: F) -> Result<Entry<K, V>, UpdateError<U>>
where
F: FnOnce(&V) -> Result<Option<V>, U>,
U: Error + Debug + 'static,
{
let (pos, (_, v)) = self.get_record_and_pos(k).ok_or(UpdateError::KeyNotFound)?;
match f(v).map_err(UpdateError::ValueCallbackError)? {
None => {
if self.0.len() == 2 {
let to_keep = if pos == 0 { &self.0[1] } else { &self.0[0] };
Ok(Entry::Leaf(h, to_keep.0.clone(), to_keep.1.clone()))
} else {
let col =
Collision::from_box(helper::clone_array_and_remove_at_pos(&self.0, pos));
Ok(Entry::LeafMany(h, col))
}
}
Some(newv) => {
let newcol = Collision::from_box(helper::clone_array_and_set_at_pos(
&self.0,
(k.clone(), newv),
pos,
));
Ok(Entry::LeafMany(h, newcol))
}
}
}
pub fn replace(&self, k: &K, v: V) -> Result<(Self, V), ReplaceError> {
let (pos, (_, oldv)) = self
.get_record_and_pos(k)
.ok_or(ReplaceError::KeyNotFound)?;
let newcol = Collision::from_box(helper::clone_array_and_set_at_pos(
&self.0,
(k.clone(), v),
pos,
));
Ok((newcol, oldv.clone()))
}
pub fn replace_with<F>(&self, k: &K, f: F) -> Result<Self, ReplaceError>
where
F: FnOnce(&V) -> V,
{
let (pos, (_, oldv)) = self
.get_record_and_pos(k)
.ok_or(ReplaceError::KeyNotFound)?;
let v = f(oldv);
let newcol = Collision::from_box(helper::clone_array_and_set_at_pos(
&self.0,
(k.clone(), v),
pos,
));
Ok(newcol)
}
}
#[derive(Debug)]
pub enum Entry<K, V> {
Leaf(HashedKey, K, V),
LeafMany(HashedKey, Collision<K, V>),
SubNode(Node<K, V>),
}
impl<K, V> Node<K, V> {
pub fn new() -> Self {
Node {
bitmap: SmallBitmap::new(),
children: Vec::with_capacity(0).into(),
}
}
pub fn singleton(idx: LevelIndex, child: SharedRef<Entry<K, V>>) -> Self {
Node {
bitmap: SmallBitmap::once(idx),
children: vec![child].into(),
}
}
pub fn is_empty(&self) -> bool {
self.bitmap.is_empty()
}
pub fn number_children(&self) -> usize {
self.bitmap.present()
}
pub fn get_child(&self, at: ArrayIndex) -> &SharedRef<Entry<K, V>> {
assert!(!at.is_not_found());
&self.children[at.get_found()]
}
pub fn set_at(&self, idx: LevelIndex, child: SharedRef<Entry<K, V>>) -> Self {
assert!(!self.bitmap.is_set(idx));
let pos = self.bitmap.get_sparse_pos(idx);
let v = helper::clone_array_and_insert_at_pos(&self.children, child, pos.get_found());
Node {
bitmap: self.bitmap.set_index(idx),
children: v,
}
}
pub fn clear_at(&self, idx: LevelIndex) -> Option<Self> {
assert!(self.bitmap.is_set(idx));
let new_bitmap = self.bitmap.clear_index(idx);
if new_bitmap.is_empty() {
None
} else {
let pos = self.bitmap.get_sparse_pos(idx);
let v = helper::clone_array_and_remove_at_pos(&self.children, pos.get_found());
Some(Node {
bitmap: new_bitmap,
children: v,
})
}
}
pub fn replace_at(&self, idx: ArrayIndex, child: SharedRef<Entry<K, V>>) -> Self {
let mut v = self.children.clone();
v[idx.get_found()] = child;
Node {
bitmap: self.bitmap,
children: v,
}
}
pub fn clear_or_replace_at(
&self,
idx: LevelIndex,
child: Option<SharedRef<Entry<K, V>>>,
) -> Option<Self> {
assert!(self.bitmap.is_set(idx));
match child {
None => self.clear_at(idx),
Some(v) => {
let aidx = self.bitmap.get_index_sparse(idx);
Some(self.replace_at(aidx, v))
}
}
}
pub fn iter(&self) -> NodeIter<K, V> {
self.children.iter()
}
}
pub fn insert_rec<K: Clone + PartialEq, V: Clone>(
node: &Node<K, V>,
hash: HashedKey,
lvl: usize,
key: K,
value: V,
) -> Result<Node<K, V>, InsertError> {
let level_hash = hash.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
let e = SharedRef::new(Entry::Leaf(hash, key, value));
Ok(node.set_at(level_hash, e))
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, lv) => {
if *lh == hash {
if lk == &key {
return Err(InsertError::EntryExists);
}
let dat = vec![(lk.clone(), lv.clone()), (key, value)];
let e = SharedRef::new(Entry::LeafMany(*lh, Collision::from_vec(dat)));
Ok(node.replace_at(idx, e))
} else {
let leaf_idx = lh.level_index(lvl + 1);
let entry_next_idx = hash.level_index(lvl + 1);
let subnode = Node::singleton(leaf_idx, SharedRef::clone(node.get_child(idx)));
if entry_next_idx != leaf_idx {
let subnode = subnode.set_at(
entry_next_idx,
SharedRef::new(Entry::Leaf(hash, key, value)),
);
Ok(node.replace_at(idx, SharedRef::new(Entry::SubNode(subnode))))
} else {
let r = insert_rec(&subnode, hash, lvl + 1, key, value)?;
let e = SharedRef::new(Entry::SubNode(r));
Ok(node.replace_at(idx, e))
}
}
}
Entry::LeafMany(lh, col) => {
assert_eq!(*lh, hash);
let col = col.insert(key, value)?;
Ok(node.replace_at(idx, SharedRef::new(Entry::LeafMany(*lh, col))))
}
Entry::SubNode(sub) => {
if lvl > 13 {
unreachable!()
} else {
let r = insert_rec(sub, hash, lvl + 1, key, value)?;
let e = SharedRef::new(Entry::SubNode(r));
Ok(node.replace_at(idx, e))
}
}
}
}
}
pub enum LookupRet<'a, K, V> {
Found(&'a V),
NotFound,
ContinueIn(&'a Node<K, V>),
}
pub fn lookup_one<'a, Q: PartialEq, K: PartialEq + Borrow<Q>, V>(
node: &'a Node<K, V>,
h: &HashedKey,
lvl: usize,
k: &Q,
) -> LookupRet<'a, K, V> {
let level_hash = h.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
LookupRet::NotFound
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, lv) => {
if lh == h && lk.borrow() == k {
LookupRet::Found(lv)
} else {
LookupRet::NotFound
}
}
Entry::LeafMany(lh, col) => {
if lh != h {
LookupRet::NotFound
} else {
match col.0.iter().find(|(lk, _)| lk.borrow() == k) {
None => LookupRet::NotFound,
Some(lkv) => LookupRet::Found(&lkv.1),
}
}
}
Entry::SubNode(sub) => LookupRet::ContinueIn(sub),
}
}
}
pub fn remove_eq_rec<Q, K, V>(
node: &Node<K, V>,
h: HashedKey,
lvl: usize,
k: &Q,
v: &V,
) -> Result<Option<Node<K, V>>, RemoveError>
where
Q: PartialEq,
K: Borrow<Q> + PartialEq + Clone,
V: PartialEq + Clone,
{
let level_hash = h.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
Err(RemoveError::KeyNotFound)
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, lv) => {
if *lh == h && lk.borrow() == k {
if lv == v {
Ok(node.clear_at(level_hash))
} else {
Err(RemoveError::ValueNotMatching)
}
} else {
Err(RemoveError::KeyNotFound)
}
}
Entry::LeafMany(lh, col) => {
assert_eq!(*lh, h);
let replacement = col.remove_match(h, k, v)?;
Ok(Some(node.replace_at(idx, SharedRef::new(replacement))))
}
Entry::SubNode(sub) => match remove_eq_rec(sub, h, lvl + 1, k, v)? {
None => Ok(node.clear_at(level_hash)),
Some(newsub) => {
let e = Entry::SubNode(newsub);
Ok(Some(node.replace_at(idx, SharedRef::new(e))))
}
},
}
}
}
pub fn remove_rec<Q, K, V>(
node: &Node<K, V>,
h: HashedKey,
lvl: usize,
k: &Q,
) -> Result<Option<Node<K, V>>, RemoveError>
where
Q: PartialEq,
K: Borrow<Q> + PartialEq + Clone,
V: Clone,
{
let level_hash = h.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
Err(RemoveError::KeyNotFound)
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, _) => {
if *lh == h && lk.borrow() == k {
Ok(node.clear_at(level_hash))
} else {
Err(RemoveError::KeyNotFound)
}
}
Entry::LeafMany(lh, col) => {
assert_eq!(*lh, h);
let replacement = col.remove(h, k)?;
Ok(Some(node.replace_at(idx, SharedRef::new(replacement))))
}
Entry::SubNode(sub) => match remove_rec(sub, h, lvl + 1, k)? {
None => Ok(node.clear_at(level_hash)),
Some(newsub) => {
let e = Entry::SubNode(newsub);
Ok(Some(node.replace_at(idx, SharedRef::new(e))))
}
},
}
}
}
pub fn update_rec<K, V, F, U>(
node: &Node<K, V>,
h: HashedKey,
lvl: usize,
k: &K,
f: F,
) -> Result<Option<Node<K, V>>, UpdateError<U>>
where
K: PartialEq + Clone,
V: Clone,
F: FnOnce(&V) -> Result<Option<V>, U>,
U: Error + Debug + 'static,
{
let level_hash = h.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
Err(UpdateError::KeyNotFound)
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, lv) => {
if *lh == h && lk == k {
let newv = f(lv).map_err(UpdateError::ValueCallbackError)?;
Ok(node.clear_or_replace_at(
level_hash,
newv.map(|x| SharedRef::new(Entry::Leaf(*lh, lk.clone(), x))),
))
} else {
Err(UpdateError::KeyNotFound)
}
}
Entry::LeafMany(lh, col) => {
assert_eq!(*lh, h);
let replacement = col.update(h, k, f)?;
Ok(Some(node.replace_at(idx, SharedRef::new(replacement))))
}
Entry::SubNode(sub) => match update_rec(sub, h, lvl + 1, k, f)? {
None => Ok(node.clear_at(level_hash)),
Some(newsub) => {
let e = Entry::SubNode(newsub);
Ok(Some(node.replace_at(idx, SharedRef::new(e))))
}
},
}
}
}
pub fn replace_rec<K: PartialEq + Clone, V: Clone>(
node: &Node<K, V>,
h: HashedKey,
lvl: usize,
k: &K,
v: V,
) -> Result<(Node<K, V>, V), ReplaceError> {
let level_hash = h.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
Err(ReplaceError::KeyNotFound)
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, lv) => {
if *lh == h && lk == k {
let new_ent = SharedRef::new(Entry::Leaf(*lh, lk.clone(), v));
Ok((node.replace_at(idx, new_ent), lv.clone()))
} else {
Err(ReplaceError::KeyNotFound)
}
}
Entry::LeafMany(lh, col) => {
assert_eq!(*lh, h);
let (replacement, old_value) = col.replace(k, v)?;
Ok((
node.replace_at(idx, SharedRef::new(Entry::LeafMany(*lh, replacement))),
old_value,
))
}
Entry::SubNode(sub) => {
let (newsub, oldv) = replace_rec(sub, h, lvl + 1, k, v)?;
let e = Entry::SubNode(newsub);
Ok((node.replace_at(idx, SharedRef::new(e)), oldv))
}
}
}
}
pub fn replace_with_rec<K: PartialEq + Clone, V: Clone, F>(
node: &Node<K, V>,
h: HashedKey,
lvl: usize,
k: &K,
f: F,
) -> Result<Node<K, V>, ReplaceError>
where
F: FnOnce(&V) -> V,
{
let level_hash = h.level_index(lvl);
let idx = node.bitmap.get_index_sparse(level_hash);
if idx.is_not_found() {
Err(ReplaceError::KeyNotFound)
} else {
match node.get_child(idx).as_ref() {
Entry::Leaf(lh, lk, lv) => {
if *lh == h && lk == k {
let new_ent = SharedRef::new(Entry::Leaf(*lh, lk.clone(), f(lv)));
Ok(node.replace_at(idx, new_ent))
} else {
Err(ReplaceError::KeyNotFound)
}
}
Entry::LeafMany(lh, col) => {
assert_eq!(*lh, h);
let replacement = col.replace_with(k, f)?;
Ok(node.replace_at(idx, SharedRef::new(Entry::LeafMany(*lh, replacement))))
}
Entry::SubNode(sub) => {
let newsub = replace_with_rec(sub, h, lvl + 1, k, f)?;
let e = Entry::SubNode(newsub);
Ok(node.replace_at(idx, SharedRef::new(e)))
}
}
}
}
pub fn size_rec<K, V>(node: &Node<K, V>) -> usize {
let mut sum = 0;
for c in node.children.iter() {
match &c.as_ref() {
Entry::Leaf(_, _, _) => sum += 1,
Entry::LeafMany(_, col) => sum += col.len(),
Entry::SubNode(sub) => sum += size_rec(sub),
}
}
sum
}
pub mod debug {
use super::*;
use std::cmp;
pub fn depth_rec<K, V>(node: &Node<K, V>) -> usize {
let mut max_depth = 0;
for c in node.children.iter() {
match &c.as_ref() {
Entry::Leaf(_, _, _) => {}
Entry::LeafMany(_, _) => {}
Entry::SubNode(sub) => {
let child_depth = depth_rec(sub);
max_depth = cmp::max(max_depth, child_depth)
}
}
}
max_depth
}
}