#![allow(unstable_name_collisions)]
mod branch;
pub mod bytetable;
mod entry;
mod leaf;
use arrayvec::ArrayVec;
use branch::*;
pub use entry::Entry;
use leaf::*;
pub use bytetable::*;
use rand::thread_rng;
use rand::RngCore;
use std::cmp::Reverse;
use std::convert::TryInto;
use std::fmt;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ptr::NonNull;
use std::sync::Once;
#[cfg(not(target_pointer_width = "64"))]
compile_error!("PATCH tagged pointers require 64-bit targets");
static mut SIP_KEY: [u8; 16] = [0; 16];
static INIT: Once = Once::new();
fn init_sip_key() {
INIT.call_once(|| {
bytetable::init();
let mut rng = thread_rng();
unsafe {
rng.fill_bytes(&mut SIP_KEY[..]);
}
});
}
pub const fn build_segmentation<const N: usize, const M: usize>(lens: [usize; M]) -> [usize; N] {
let mut res = [0; N];
let mut seg = 0;
let mut off = 0;
while seg < M {
let len = lens[seg];
let mut i = 0;
while i < len {
res[off + i] = seg;
i += 1;
}
off += len;
seg += 1;
}
res
}
pub const fn identity_map<const N: usize>() -> [usize; N] {
let mut res = [0; N];
let mut i = 0;
while i < N {
res[i] = i;
i += 1;
}
res
}
pub const fn build_key_to_tree<const N: usize, const M: usize>(
lens: [usize; M],
perm: [usize; M],
) -> [usize; N] {
let mut key_starts = [0; M];
let mut off = 0;
let mut i = 0;
while i < M {
key_starts[i] = off;
off += lens[i];
i += 1;
}
let mut tree_starts = [0; M];
off = 0;
i = 0;
while i < M {
let seg = perm[i];
tree_starts[seg] = off;
off += lens[seg];
i += 1;
}
let mut res = [0; N];
let mut seg = 0;
while seg < M {
let len = lens[seg];
let ks = key_starts[seg];
let ts = tree_starts[seg];
let mut j = 0;
while j < len {
res[ks + j] = ts + j;
j += 1;
}
seg += 1;
}
res
}
pub const fn invert<const N: usize>(arr: [usize; N]) -> [usize; N] {
let mut res = [0; N];
let mut i = 0;
while i < N {
res[arr[i]] = i;
i += 1;
}
res
}
#[doc(hidden)]
#[macro_export]
macro_rules! key_segmentation {
(@count $($e:expr),* $(,)?) => {
<[()]>::len(&[$($crate::key_segmentation!(@sub $e)),*])
};
(@sub $e:expr) => { () };
($(#[$meta:meta])* $name:ident, $len:expr, [$($seg_len:expr),+ $(,)?]) => {
$(#[$meta])*
#[derive(Copy, Clone, Debug)]
pub struct $name;
impl $name {
pub const SEG_LENS: [usize; $crate::key_segmentation!(@count $($seg_len),*)] = [$($seg_len),*];
}
impl $crate::patch::KeySegmentation<$len> for $name {
const SEGMENTS: [usize; $len] = $crate::patch::build_segmentation::<$len, {$crate::key_segmentation!(@count $($seg_len),*)}>(Self::SEG_LENS);
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! key_schema {
(@count $($e:expr),* $(,)?) => {
<[()]>::len(&[$($crate::key_schema!(@sub $e)),*])
};
(@sub $e:expr) => { () };
($(#[$meta:meta])* $name:ident, $seg:ty, $len:expr, [$($perm:expr),+ $(,)?]) => {
$(#[$meta])*
#[derive(Copy, Clone, Debug)]
pub struct $name;
impl $crate::patch::KeySchema<$len> for $name {
type Segmentation = $seg;
const SEGMENT_PERM: &'static [usize] = &[$($perm),*];
const KEY_TO_TREE: [usize; $len] = $crate::patch::build_key_to_tree::<$len, {$crate::key_schema!(@count $($perm),*)}>(<$seg>::SEG_LENS, [$($perm),*]);
const TREE_TO_KEY: [usize; $len] = $crate::patch::invert(Self::KEY_TO_TREE);
}
};
}
pub trait KeySchema<const KEY_LEN: usize>: Copy + Clone + Debug {
type Segmentation: KeySegmentation<KEY_LEN>;
const SEGMENT_PERM: &'static [usize];
const KEY_TO_TREE: [usize; KEY_LEN];
const TREE_TO_KEY: [usize; KEY_LEN];
fn tree_ordered(key: &[u8; KEY_LEN]) -> [u8; KEY_LEN] {
let mut new_key = [0; KEY_LEN];
let mut i = 0;
while i < KEY_LEN {
new_key[Self::KEY_TO_TREE[i]] = key[i];
i += 1;
}
new_key
}
fn key_ordered(tree_key: &[u8; KEY_LEN]) -> [u8; KEY_LEN] {
let mut new_key = [0; KEY_LEN];
let mut i = 0;
while i < KEY_LEN {
new_key[Self::TREE_TO_KEY[i]] = tree_key[i];
i += 1;
}
new_key
}
fn segment_of_tree_depth(at_depth: usize) -> usize {
<Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[at_depth]]
}
fn same_segment_tree(a: usize, b: usize) -> bool {
<Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[a]]
== <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[b]]
}
}
pub trait KeySegmentation<const KEY_LEN: usize>: Copy + Clone + Debug {
const SEGMENTS: [usize; KEY_LEN];
}
#[derive(Copy, Clone, Debug)]
pub struct IdentitySchema {}
#[derive(Copy, Clone, Debug)]
pub struct SingleSegmentation {}
impl<const KEY_LEN: usize> KeySchema<KEY_LEN> for IdentitySchema {
type Segmentation = SingleSegmentation;
const SEGMENT_PERM: &'static [usize] = &[0];
const KEY_TO_TREE: [usize; KEY_LEN] = identity_map::<KEY_LEN>();
const TREE_TO_KEY: [usize; KEY_LEN] = identity_map::<KEY_LEN>();
}
impl<const KEY_LEN: usize> KeySegmentation<KEY_LEN> for SingleSegmentation {
const SEGMENTS: [usize; KEY_LEN] = [0; KEY_LEN];
}
#[allow(dead_code)]
#[derive(Debug, PartialEq, Copy, Clone)]
#[repr(u8)]
pub(crate) enum HeadTag {
Leaf = 0,
Branch2 = 1,
Branch4 = 2,
Branch8 = 3,
Branch16 = 4,
Branch32 = 5,
Branch64 = 6,
Branch128 = 7,
Branch256 = 8,
}
impl HeadTag {
#[inline]
fn from_raw(raw: u8) -> Self {
debug_assert!(raw <= HeadTag::Branch256 as u8);
unsafe { std::mem::transmute(raw) }
}
}
pub(crate) enum BodyPtr<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
Leaf(NonNull<Leaf<KEY_LEN, V>>),
Branch(branch::BranchNN<KEY_LEN, O, V>),
}
pub(crate) enum BodyRef<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
Leaf(&'a Leaf<KEY_LEN, V>),
Branch(&'a Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V>>], V>),
}
pub(crate) enum BodyMut<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
Leaf(&'a mut Leaf<KEY_LEN, V>),
Branch(&'a mut Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V>>], V>),
}
pub(crate) trait Body {
fn tag(body: NonNull<Self>) -> HeadTag;
}
#[repr(C)]
pub(crate) struct Head<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
tptr: std::ptr::NonNull<u8>,
key_ordering: PhantomData<O>,
key_segments: PhantomData<O::Segmentation>,
value: PhantomData<V>,
}
unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Send for Head<KEY_LEN, O, V> {}
unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Sync for Head<KEY_LEN, O, V> {}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Head<KEY_LEN, O, V> {
const TAG_MASK: u64 = 0x0f;
const BODY_MASK: u64 = 0x00_ff_ff_ff_ff_ff_ff_f0;
const KEY_MASK: u64 = 0xff_00_00_00_00_00_00_00;
pub(crate) fn new<T: Body + ?Sized>(key: u8, body: NonNull<T>) -> Self {
unsafe {
let tptr =
std::ptr::NonNull::new_unchecked((body.as_ptr() as *mut u8).map_addr(|addr| {
debug_assert_eq!(addr as u64 & Self::TAG_MASK, 0);
((addr as u64 & Self::BODY_MASK)
| ((key as u64) << 56)
| (<T as Body>::tag(body) as u64)) as usize
}));
Self {
tptr,
key_ordering: PhantomData,
key_segments: PhantomData,
value: PhantomData,
}
}
}
#[inline]
pub(crate) fn tag(&self) -> HeadTag {
HeadTag::from_raw((self.tptr.as_ptr() as u64 & Self::TAG_MASK) as u8)
}
#[inline]
pub(crate) fn key(&self) -> u8 {
(self.tptr.as_ptr() as u64 >> 56) as u8
}
#[inline]
pub(crate) fn with_key(mut self, key: u8) -> Self {
self.tptr =
std::ptr::NonNull::new(self.tptr.as_ptr().map_addr(|addr| {
((addr as u64 & !Self::KEY_MASK) | ((key as u64) << 56)) as usize
}))
.unwrap();
self
}
#[inline]
pub(crate) fn set_body<T: Body + ?Sized>(&mut self, body: NonNull<T>) {
unsafe {
self.tptr = NonNull::new_unchecked((body.as_ptr() as *mut u8).map_addr(|addr| {
debug_assert_eq!(addr as u64 & Self::TAG_MASK, 0);
((addr as u64 & Self::BODY_MASK)
| (self.tptr.as_ptr() as u64 & Self::KEY_MASK)
| (<T as Body>::tag(body) as u64)) as usize
}))
}
}
pub(crate) fn with_start(self, new_start_depth: usize) -> Head<KEY_LEN, O, V> {
let leaf_key = self.childleaf_key();
let i = O::TREE_TO_KEY[new_start_depth];
let key = leaf_key[i];
self.with_key(key)
}
pub(crate) fn body(&self) -> BodyPtr<KEY_LEN, O, V> {
unsafe {
let ptr = NonNull::new_unchecked(self.tptr.as_ptr().map_addr(|addr| {
let masked = (addr as u64) & Self::BODY_MASK;
masked as usize
}));
match self.tag() {
HeadTag::Leaf => BodyPtr::Leaf(ptr.cast()),
branch_tag => {
let count = 1 << (branch_tag as usize);
BodyPtr::Branch(NonNull::new_unchecked(std::ptr::slice_from_raw_parts(
ptr.as_ptr(),
count,
)
as *mut Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V>>], V>))
}
}
}
}
pub(crate) fn body_mut(&mut self) -> BodyMut<'_, KEY_LEN, O, V> {
unsafe {
match self.body() {
BodyPtr::Leaf(mut leaf) => BodyMut::Leaf(leaf.as_mut()),
BodyPtr::Branch(mut branch) => {
let mut branch_nn = branch;
if Branch::rc_cow(&mut branch_nn).is_some() {
self.set_body(branch_nn);
BodyMut::Branch(branch_nn.as_mut())
} else {
BodyMut::Branch(branch.as_mut())
}
}
}
}
}
pub(crate) fn body_ref(&self) -> BodyRef<'_, KEY_LEN, O, V> {
match self.body() {
BodyPtr::Leaf(nn) => BodyRef::Leaf(unsafe { nn.as_ref() }),
BodyPtr::Branch(nn) => BodyRef::Branch(unsafe { nn.as_ref() }),
}
}
pub(crate) fn count(&self) -> u64 {
match self.body_ref() {
BodyRef::Leaf(_) => 1,
BodyRef::Branch(branch) => branch.leaf_count,
}
}
pub(crate) fn count_segment(&self, at_depth: usize) -> u64 {
match self.body_ref() {
BodyRef::Leaf(_) => 1,
BodyRef::Branch(branch) => branch.count_segment(at_depth),
}
}
pub(crate) fn hash(&self) -> u128 {
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.hash,
BodyRef::Branch(branch) => branch.hash,
}
}
pub(crate) fn end_depth(&self) -> usize {
match self.body_ref() {
BodyRef::Leaf(_) => KEY_LEN,
BodyRef::Branch(branch) => branch.end_depth as usize,
}
}
pub(crate) fn childleaf_ptr(&self) -> *const Leaf<KEY_LEN, V> {
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf as *const Leaf<KEY_LEN, V>,
BodyRef::Branch(branch) => branch.childleaf_ptr(),
}
}
pub(crate) fn childleaf_key(&self) -> &[u8; KEY_LEN] {
match self.body_ref() {
BodyRef::Leaf(leaf) => &leaf.key,
BodyRef::Branch(branch) => &branch.childleaf().key,
}
}
pub(crate) fn first_divergence(
&self,
other: &Self,
start_depth: usize,
) -> Option<(usize, u8, u8)> {
let limit = std::cmp::min(std::cmp::min(self.end_depth(), other.end_depth()), KEY_LEN);
debug_assert!(limit <= KEY_LEN);
let this_key = self.childleaf_key();
let other_key = other.childleaf_key();
let mut depth = start_depth;
while depth < limit {
let i = O::TREE_TO_KEY[depth];
let a = this_key[i];
let b = other_key[i];
if a != b {
return Some((depth, a, b));
}
depth += 1;
}
None
}
pub(crate) fn remove_leaf(
slot: &mut Option<Self>,
leaf_key: &[u8; KEY_LEN],
start_depth: usize,
) {
if let Some(this) = slot {
let end_depth = std::cmp::min(this.end_depth(), KEY_LEN);
if !this.has_prefix::<KEY_LEN>(start_depth, leaf_key) {
return;
}
if this.tag() == HeadTag::Leaf {
slot.take();
} else {
let mut ed = crate::patch::branch::BranchMut::from_head(this);
let key = leaf_key[end_depth];
ed.modify_child(key, |mut opt| {
Self::remove_leaf(&mut opt, leaf_key, end_depth);
opt
});
if ed.leaf_count == 1 {
let mut remaining: Option<Head<KEY_LEN, O, V>> = None;
for slot_child in &mut ed.child_table {
if let Some(child) = slot_child.take() {
remaining = Some(child.with_start(start_depth));
break;
}
}
drop(ed);
if let Some(child) = remaining {
slot.replace(child);
}
} else {
drop(ed);
}
}
}
}
pub(crate) fn insert_leaf(mut this: Self, leaf: Self, start_depth: usize) -> Self {
if let Some((depth, this_byte_key, leaf_byte_key)) =
this.first_divergence(&leaf, start_depth)
{
let old_key = this.key();
let new_body = Branch::new(
depth,
this.with_key(this_byte_key),
leaf.with_key(leaf_byte_key),
);
return Head::new(old_key, new_body);
}
let end_depth = this.end_depth();
if end_depth != KEY_LEN {
let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
let inserted = leaf.with_start(ed.end_depth as usize);
let key = inserted.key();
ed.modify_child(key, |opt| match opt {
Some(old) => Some(Head::insert_leaf(old, inserted, end_depth)),
None => Some(inserted),
});
}
this
}
pub(crate) fn replace_leaf(mut this: Self, leaf: Self, start_depth: usize) -> Self {
if let Some((depth, this_byte_key, leaf_byte_key)) =
this.first_divergence(&leaf, start_depth)
{
let old_key = this.key();
let new_body = Branch::new(
depth,
this.with_key(this_byte_key),
leaf.with_key(leaf_byte_key),
);
return Head::new(old_key, new_body);
}
let end_depth = this.end_depth();
if end_depth == KEY_LEN {
let old_key = this.key();
return leaf.with_key(old_key);
} else {
let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
let inserted = leaf.with_start(ed.end_depth as usize);
let key = inserted.key();
ed.modify_child(key, |opt| match opt {
Some(old) => Some(Head::replace_leaf(old, inserted, end_depth)),
None => Some(inserted),
});
}
this
}
pub(crate) fn union(mut this: Self, mut other: Self, at_depth: usize) -> Self {
if this.hash() == other.hash() {
return this;
}
if let Some((depth, this_byte_key, other_byte_key)) =
this.first_divergence(&other, at_depth)
{
let old_key = this.key();
let new_body = Branch::new(
depth,
this.with_key(this_byte_key),
other.with_key(other_byte_key),
);
return Head::new(old_key, new_body);
}
let this_depth = this.end_depth();
let other_depth = other.end_depth();
if this_depth < other_depth {
let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
let inserted = other.with_start(ed.end_depth as usize);
let key = inserted.key();
ed.modify_child(key, |opt| match opt {
Some(old) => Some(Head::union(old, inserted, this_depth)),
None => Some(inserted),
});
drop(ed);
return this;
}
if other_depth < this_depth {
let old_key = this.key();
let this_head = this;
let mut ed = crate::patch::branch::BranchMut::from_head(&mut other);
let inserted = this_head.with_start(ed.end_depth as usize);
let key = inserted.key();
ed.modify_child(key, |opt| match opt {
Some(old) => Some(Head::union(old, inserted, other_depth)),
None => Some(inserted),
});
drop(ed);
return other.with_key(old_key);
}
let BodyMut::Branch(other_branch_ref) = other.body_mut() else {
unreachable!();
};
{
let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
for other_child in other_branch_ref
.child_table
.iter_mut()
.filter_map(Option::take)
{
let inserted = other_child.with_start(ed.end_depth as usize);
let key = inserted.key();
ed.modify_child(key, |opt| match opt {
Some(old) => Some(Head::union(old, inserted, this_depth)),
None => Some(inserted),
});
}
}
this
}
pub(crate) fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
&self,
prefix: &[u8; PREFIX_LEN],
at_depth: usize,
f: &mut F,
) where
F: FnMut(&[u8; INFIX_LEN]),
{
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.infixes::<PREFIX_LEN, INFIX_LEN, O, F>(prefix, at_depth, f),
BodyRef::Branch(branch) => {
branch.infixes::<PREFIX_LEN, INFIX_LEN, F>(prefix, at_depth, f)
}
}
}
pub(crate) fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
&self,
prefix: &[u8; PREFIX_LEN],
at_depth: usize,
min_infix: &[u8; INFIX_LEN],
max_infix: &[u8; INFIX_LEN],
f: &mut F,
) where
F: FnMut(&[u8; INFIX_LEN]),
{
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.infixes_range::<PREFIX_LEN, INFIX_LEN, O, F>(prefix, at_depth, min_infix, max_infix, f),
BodyRef::Branch(branch) => {
branch.infixes_range::<PREFIX_LEN, INFIX_LEN, F>(prefix, at_depth, min_infix, max_infix, f)
}
}
}
pub(crate) fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
&self,
prefix: &[u8; PREFIX_LEN],
at_depth: usize,
min_infix: &[u8; INFIX_LEN],
max_infix: &[u8; INFIX_LEN],
) -> u64 {
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.count_range::<PREFIX_LEN, INFIX_LEN, O>(prefix, at_depth, min_infix, max_infix),
BodyRef::Branch(branch) => branch.count_range::<PREFIX_LEN, INFIX_LEN>(prefix, at_depth, min_infix, max_infix),
}
}
pub(crate) fn has_prefix<const PREFIX_LEN: usize>(
&self,
at_depth: usize,
prefix: &[u8; PREFIX_LEN],
) -> bool {
const {
assert!(PREFIX_LEN <= KEY_LEN);
}
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.has_prefix::<O>(at_depth, prefix),
BodyRef::Branch(branch) => branch.has_prefix::<PREFIX_LEN>(at_depth, prefix),
}
}
pub(crate) fn get<'a>(&'a self, at_depth: usize, key: &[u8; KEY_LEN]) -> Option<&'a V>
where
O: 'a,
{
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.get::<O>(at_depth, key),
BodyRef::Branch(branch) => branch.get(at_depth, key),
}
}
pub(crate) fn segmented_len<const PREFIX_LEN: usize>(
&self,
at_depth: usize,
prefix: &[u8; PREFIX_LEN],
) -> u64 {
match self.body_ref() {
BodyRef::Leaf(leaf) => leaf.segmented_len::<O, PREFIX_LEN>(at_depth, prefix),
BodyRef::Branch(branch) => branch.segmented_len::<PREFIX_LEN>(at_depth, prefix),
}
}
pub(crate) fn intersect(&self, other: &Self, at_depth: usize) -> Option<Self> {
if self.hash() == other.hash() {
return Some(self.clone());
}
if self.first_divergence(other, at_depth).is_some() {
return None;
}
let self_depth = self.end_depth();
let other_depth = other.end_depth();
if self_depth < other_depth {
let BodyRef::Branch(branch) = self.body_ref() else {
unreachable!();
};
return branch
.child_table
.table_get(other.childleaf_key()[O::TREE_TO_KEY[self_depth]])
.and_then(|self_child| other.intersect(self_child, self_depth));
}
if other_depth < self_depth {
let BodyRef::Branch(other_branch) = other.body_ref() else {
unreachable!();
};
return other_branch
.child_table
.table_get(self.childleaf_key()[O::TREE_TO_KEY[other_depth]])
.and_then(|other_child| self.intersect(other_child, other_depth));
}
let BodyRef::Branch(self_branch) = self.body_ref() else {
unreachable!();
};
let BodyRef::Branch(other_branch) = other.body_ref() else {
unreachable!();
};
let mut intersected_children = self_branch
.child_table
.iter()
.filter_map(Option::as_ref)
.filter_map(|self_child| {
let other_child = other_branch.child_table.table_get(self_child.key())?;
self_child.intersect(other_child, self_depth)
});
let first_child = intersected_children.next()?;
let Some(second_child) = intersected_children.next() else {
return Some(first_child);
};
let new_branch = Branch::new(
self_depth,
first_child.with_start(self_depth),
second_child.with_start(self_depth),
);
let mut head_for_branch = Head::new(0, new_branch);
{
let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
for child in intersected_children {
let inserted = child.with_start(self_depth);
let k = inserted.key();
ed.modify_child(k, |_opt| Some(inserted));
}
}
Some(head_for_branch)
}
pub(crate) fn difference(&self, other: &Self, at_depth: usize) -> Option<Self> {
if self.hash() == other.hash() {
return None;
}
if self.first_divergence(other, at_depth).is_some() {
return Some(self.clone());
}
let self_depth = self.end_depth();
let other_depth = other.end_depth();
if self_depth < other_depth {
let mut new_branch = self.clone();
let other_byte_key = other.childleaf_key()[O::TREE_TO_KEY[self_depth]];
{
let mut ed = crate::patch::branch::BranchMut::from_head(&mut new_branch);
ed.modify_child(other_byte_key, |opt| {
opt.and_then(|child| child.difference(other, self_depth))
});
}
return Some(new_branch);
}
if other_depth < self_depth {
let BodyRef::Branch(other_branch) = other.body_ref() else {
unreachable!();
};
let self_byte_key = self.childleaf_key()[O::TREE_TO_KEY[other_depth]];
if let Some(other_child) = other_branch.child_table.table_get(self_byte_key) {
return self.difference(other_child, at_depth);
} else {
return Some(self.clone());
}
}
let BodyRef::Branch(self_branch) = self.body_ref() else {
unreachable!();
};
let BodyRef::Branch(other_branch) = other.body_ref() else {
unreachable!();
};
let mut differenced_children = self_branch
.child_table
.iter()
.filter_map(Option::as_ref)
.filter_map(|self_child| {
if let Some(other_child) = other_branch.child_table.table_get(self_child.key()) {
self_child.difference(other_child, self_depth)
} else {
Some(self_child.clone())
}
});
let first_child = differenced_children.next()?;
let second_child = match differenced_children.next() {
Some(sc) => sc,
None => return Some(first_child),
};
let new_branch = Branch::new(
self_depth,
first_child.with_start(self_depth),
second_child.with_start(self_depth),
);
let mut head_for_branch = Head::new(0, new_branch);
{
let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
for child in differenced_children {
let inserted = child.with_start(self_depth);
let k = inserted.key();
ed.modify_child(k, |_opt| Some(inserted));
}
}
Some(head_for_branch)
}
}
unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ByteEntry for Head<KEY_LEN, O, V> {
fn key(&self) -> u8 {
self.key()
}
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> fmt::Debug for Head<KEY_LEN, O, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.tag().fmt(f)
}
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Clone for Head<KEY_LEN, O, V> {
fn clone(&self) -> Self {
unsafe {
match self.body() {
BodyPtr::Leaf(leaf) => Self::new(self.key(), Leaf::rc_inc(leaf)),
BodyPtr::Branch(branch) => Self::new(self.key(), Branch::rc_inc(branch)),
}
}
}
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Drop for Head<KEY_LEN, O, V> {
fn drop(&mut self) {
unsafe {
match self.body() {
BodyPtr::Leaf(leaf) => Leaf::rc_dec(leaf),
BodyPtr::Branch(branch) => Branch::rc_dec(branch),
}
}
}
}
#[derive(Debug)]
pub struct PATCH<const KEY_LEN: usize, O = IdentitySchema, V = ()>
where
O: KeySchema<KEY_LEN>,
{
root: Option<Head<KEY_LEN, O, V>>,
}
impl<const KEY_LEN: usize, O, V> Clone for PATCH<KEY_LEN, O, V>
where
O: KeySchema<KEY_LEN>,
{
fn clone(&self) -> Self {
Self {
root: self.root.clone(),
}
}
}
impl<const KEY_LEN: usize, O, V> Default for PATCH<KEY_LEN, O, V>
where
O: KeySchema<KEY_LEN>,
{
fn default() -> Self {
Self::new()
}
}
impl<const KEY_LEN: usize, O, V> PATCH<KEY_LEN, O, V>
where
O: KeySchema<KEY_LEN>,
{
pub fn new() -> Self {
init_sip_key();
PATCH { root: None }
}
pub fn insert(&mut self, entry: &Entry<KEY_LEN, V>) {
if self.root.is_some() {
let this = self.root.take().expect("root should not be empty");
let new_head = Head::insert_leaf(this, entry.leaf(), 0);
self.root.replace(new_head);
} else {
self.root.replace(entry.leaf());
}
}
pub fn replace(&mut self, entry: &Entry<KEY_LEN, V>) {
if self.root.is_some() {
let this = self.root.take().expect("root should not be empty");
let new_head = Head::replace_leaf(this, entry.leaf(), 0);
self.root.replace(new_head);
} else {
self.root.replace(entry.leaf());
}
}
pub fn remove(&mut self, key: &[u8; KEY_LEN]) {
Head::remove_leaf(&mut self.root, key, 0);
}
pub fn len(&self) -> u64 {
if let Some(root) = &self.root {
root.count()
} else {
0
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub(crate) fn root_hash(&self) -> Option<u128> {
self.root.as_ref().map(|root| root.hash())
}
pub fn get(&self, key: &[u8; KEY_LEN]) -> Option<&V> {
self.root.as_ref().and_then(|root| root.get(0, key))
}
pub fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
&self,
prefix: &[u8; PREFIX_LEN],
mut for_each: F,
) where
F: FnMut(&[u8; INFIX_LEN]),
{
const {
assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
}
assert!(
O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
&& (PREFIX_LEN + INFIX_LEN == KEY_LEN
|| !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
"INFIX_LEN must cover a whole segment"
);
if let Some(root) = &self.root {
root.infixes(prefix, 0, &mut for_each);
}
}
pub fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
&self,
prefix: &[u8; PREFIX_LEN],
min_infix: &[u8; INFIX_LEN],
max_infix: &[u8; INFIX_LEN],
mut for_each: F,
) where
F: FnMut(&[u8; INFIX_LEN]),
{
const {
assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
}
assert!(
O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
&& (PREFIX_LEN + INFIX_LEN == KEY_LEN
|| !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
"INFIX_LEN must cover a whole segment"
);
if let Some(root) = &self.root {
root.infixes_range(prefix, 0, min_infix, max_infix, &mut for_each);
}
}
pub fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
&self,
prefix: &[u8; PREFIX_LEN],
min_infix: &[u8; INFIX_LEN],
max_infix: &[u8; INFIX_LEN],
) -> u64 {
const {
assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
}
match &self.root {
Some(root) => root.count_range(prefix, 0, min_infix, max_infix),
None => 0,
}
}
pub fn has_prefix<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> bool {
const {
assert!(PREFIX_LEN <= KEY_LEN);
}
if let Some(root) = &self.root {
root.has_prefix(0, prefix)
} else {
PREFIX_LEN == 0
}
}
pub fn segmented_len<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> u64 {
const {
assert!(PREFIX_LEN <= KEY_LEN);
if PREFIX_LEN > 0 && PREFIX_LEN < KEY_LEN {
assert!(
<O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
[O::TREE_TO_KEY[PREFIX_LEN - 1]]
!= <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
[O::TREE_TO_KEY[PREFIX_LEN]],
"PREFIX_LEN must align to segment boundary",
);
}
}
if let Some(root) = &self.root {
root.segmented_len(0, prefix)
} else {
0
}
}
pub fn iter<'a>(&'a self) -> PATCHIterator<'a, KEY_LEN, O, V> {
PATCHIterator::new(self)
}
pub fn iter_ordered<'a>(&'a self) -> PATCHOrderedIterator<'a, KEY_LEN, O, V> {
PATCHOrderedIterator::new(self)
}
pub fn iter_prefix_count<'a, const PREFIX_LEN: usize>(
&'a self,
) -> PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V> {
PATCHPrefixIterator::new(self)
}
pub fn union(&mut self, other: Self) {
if let Some(other) = other.root {
if self.root.is_some() {
let this = self.root.take().expect("root should not be empty");
let merged = Head::union(this, other, 0);
self.root.replace(merged);
} else {
self.root.replace(other);
}
}
}
pub fn intersect(&self, other: &Self) -> Self {
if let Some(root) = &self.root {
if let Some(other_root) = &other.root {
return Self {
root: root.intersect(other_root, 0).map(|root| root.with_start(0)),
};
}
}
Self::new()
}
pub fn difference(&self, other: &Self) -> Self {
if let Some(root) = &self.root {
if let Some(other_root) = &other.root {
Self {
root: root.difference(other_root, 0),
}
} else {
(*self).clone()
}
} else {
Self::new()
}
}
pub fn debug_branch_fill(&self) -> [f32; 8] {
let mut counts = [0u64; 8];
let mut used = [0u64; 8];
if let Some(root) = &self.root {
let mut stack = Vec::new();
stack.push(root);
while let Some(head) = stack.pop() {
match head.body_ref() {
BodyRef::Leaf(_) => {}
BodyRef::Branch(b) => {
let size = b.child_table.len();
let idx = size.trailing_zeros() as usize - 1;
counts[idx] += 1;
used[idx] += b.child_table.iter().filter(|c| c.is_some()).count() as u64;
for child in b.child_table.iter().filter_map(|c| c.as_ref()) {
stack.push(child);
}
}
}
}
}
let mut avg = [0f32; 8];
for i in 0..8 {
if counts[i] > 0 {
let size = 1u64 << (i + 1);
avg[i] = used[i] as f32 / (counts[i] as f32 * size as f32);
}
}
avg
}
}
impl<const KEY_LEN: usize, O, V> PartialEq for PATCH<KEY_LEN, O, V>
where
O: KeySchema<KEY_LEN>,
{
fn eq(&self, other: &Self) -> bool {
self.root.as_ref().map(|root| root.hash()) == other.root.as_ref().map(|root| root.hash())
}
}
impl<const KEY_LEN: usize, O, V> Eq for PATCH<KEY_LEN, O, V> where O: KeySchema<KEY_LEN> {}
impl<'a, const KEY_LEN: usize, O, V> IntoIterator for &'a PATCH<KEY_LEN, O, V>
where
O: KeySchema<KEY_LEN>,
{
type Item = &'a [u8; KEY_LEN];
type IntoIter = PATCHIterator<'a, KEY_LEN, O, V>;
fn into_iter(self) -> Self::IntoIter {
PATCHIterator::new(self)
}
}
pub struct PATCHIterator<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
stack: ArrayVec<std::slice::Iter<'a, Option<Head<KEY_LEN, O, V>>>, KEY_LEN>,
remaining: usize,
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHIterator<'a, KEY_LEN, O, V> {
pub fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
let mut r = PATCHIterator {
stack: ArrayVec::new(),
remaining: patch.len().min(usize::MAX as u64) as usize,
};
r.stack.push(std::slice::from_ref(&patch.root).iter());
r
}
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
for PATCHIterator<'a, KEY_LEN, O, V>
{
type Item = &'a [u8; KEY_LEN];
fn next(&mut self) -> Option<Self::Item> {
let mut iter = self.stack.last_mut()?;
loop {
if let Some(child) = iter.next() {
if let Some(child) = child {
match child.body_ref() {
BodyRef::Leaf(_) => {
self.remaining = self.remaining.saturating_sub(1);
return Some(child.childleaf_key());
}
BodyRef::Branch(branch) => {
self.stack.push(branch.child_table.iter());
iter = self.stack.last_mut()?;
}
}
}
} else {
self.stack.pop();
iter = self.stack.last_mut()?;
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ExactSizeIterator
for PATCHIterator<'a, KEY_LEN, O, V>
{
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> std::iter::FusedIterator
for PATCHIterator<'a, KEY_LEN, O, V>
{
}
pub struct PATCHOrderedIterator<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V>, 256>>,
remaining: usize,
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHOrderedIterator<'a, KEY_LEN, O, V> {
pub fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
let mut r = PATCHOrderedIterator {
stack: Vec::with_capacity(KEY_LEN),
remaining: patch.len().min(usize::MAX as u64) as usize,
};
if let Some(root) = &patch.root {
r.stack.push(ArrayVec::new());
match root.body_ref() {
BodyRef::Leaf(_) => {
r.stack[0].push(root);
}
BodyRef::Branch(branch) => {
let first_level = &mut r.stack[0];
first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
first_level.sort_unstable_by_key(|&k| Reverse(k.key())); }
}
}
r
}
}
pub struct PATCHIntoIterator<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
queue: Vec<Head<KEY_LEN, O, V>>,
remaining: usize,
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHIntoIterator<KEY_LEN, O, V> {}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator for PATCHIntoIterator<KEY_LEN, O, V> {
type Item = [u8; KEY_LEN];
fn next(&mut self) -> Option<Self::Item> {
let q = &mut self.queue;
while let Some(mut head) = q.pop() {
match head.body_mut() {
BodyMut::Leaf(leaf) => {
self.remaining = self.remaining.saturating_sub(1);
return Some(leaf.key);
}
BodyMut::Branch(branch) => {
for slot in branch.child_table.iter_mut().rev() {
if let Some(c) = slot.take() {
q.push(c);
}
}
}
}
}
None
}
}
pub struct PATCHIntoOrderedIterator<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
queue: Vec<Head<KEY_LEN, O, V>>,
remaining: usize,
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
for PATCHIntoOrderedIterator<KEY_LEN, O, V>
{
type Item = [u8; KEY_LEN];
fn next(&mut self) -> Option<Self::Item> {
let q = &mut self.queue;
while let Some(mut head) = q.pop() {
match head.body_mut() {
BodyMut::Leaf(leaf) => {
self.remaining = self.remaining.saturating_sub(1);
return Some(leaf.key);
}
BodyMut::Branch(branch) => {
let slice: &mut [Option<Head<KEY_LEN, O, V>>] = &mut branch.child_table;
slice
.sort_unstable_by_key(|opt| (opt.is_none(), opt.as_ref().map(|h| h.key())));
for slot in slice.iter_mut().rev() {
if let Some(c) = slot.take() {
q.push(c);
}
}
}
}
}
None
}
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> IntoIterator for PATCH<KEY_LEN, O, V> {
type Item = [u8; KEY_LEN];
type IntoIter = PATCHIntoIterator<KEY_LEN, O, V>;
fn into_iter(self) -> Self::IntoIter {
let remaining = self.len().min(usize::MAX as u64) as usize;
let mut q = Vec::new();
if let Some(root) = self.root {
q.push(root);
}
PATCHIntoIterator {
queue: q,
remaining,
}
}
}
impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCH<KEY_LEN, O, V> {
pub fn into_iter_ordered(self) -> PATCHIntoOrderedIterator<KEY_LEN, O, V> {
let remaining = self.len().min(usize::MAX as u64) as usize;
let mut q = Vec::new();
if let Some(root) = self.root {
q.push(root);
}
PATCHIntoOrderedIterator {
queue: q,
remaining,
}
}
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
for PATCHOrderedIterator<'a, KEY_LEN, O, V>
{
type Item = &'a [u8; KEY_LEN];
fn next(&mut self) -> Option<Self::Item> {
let mut level = self.stack.last_mut()?;
loop {
if let Some(child) = level.pop() {
match child.body_ref() {
BodyRef::Leaf(_) => {
self.remaining = self.remaining.saturating_sub(1);
return Some(child.childleaf_key());
}
BodyRef::Branch(branch) => {
self.stack.push(ArrayVec::new());
level = self.stack.last_mut()?;
level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
level.sort_unstable_by_key(|&k| Reverse(k.key())); }
}
} else {
self.stack.pop();
level = self.stack.last_mut()?;
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ExactSizeIterator
for PATCHOrderedIterator<'a, KEY_LEN, O, V>
{
}
impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> std::iter::FusedIterator
for PATCHOrderedIterator<'a, KEY_LEN, O, V>
{
}
pub struct PATCHPrefixIterator<
'a,
const KEY_LEN: usize,
const PREFIX_LEN: usize,
O: KeySchema<KEY_LEN>,
V,
> {
stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V>, 256>>,
}
impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V>
PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V>
{
fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
const {
assert!(PREFIX_LEN <= KEY_LEN);
}
let mut r = PATCHPrefixIterator {
stack: Vec::with_capacity(PREFIX_LEN),
};
if let Some(root) = &patch.root {
r.stack.push(ArrayVec::new());
if root.end_depth() >= PREFIX_LEN {
r.stack[0].push(root);
} else {
let BodyRef::Branch(branch) = root.body_ref() else {
unreachable!();
};
let first_level = &mut r.stack[0];
first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
first_level.sort_unstable_by_key(|&k| Reverse(k.key())); }
}
r
}
}
impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
for PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V>
{
type Item = ([u8; PREFIX_LEN], u64);
fn next(&mut self) -> Option<Self::Item> {
let mut level = self.stack.last_mut()?;
loop {
if let Some(child) = level.pop() {
if child.end_depth() >= PREFIX_LEN {
let key = O::tree_ordered(child.childleaf_key());
let suffix_count = child.count();
return Some((key[0..PREFIX_LEN].try_into().unwrap(), suffix_count));
} else {
let BodyRef::Branch(branch) = child.body_ref() else {
unreachable!();
};
self.stack.push(ArrayVec::new());
level = self.stack.last_mut()?;
level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
level.sort_unstable_by_key(|&k| Reverse(k.key())); }
} else {
self.stack.pop();
level = self.stack.last_mut()?;
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use itertools::Itertools;
use proptest::prelude::*;
use std::collections::HashSet;
use std::convert::TryInto;
use std::iter::FromIterator;
use std::mem;
#[test]
fn head_tag() {
let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(0, NonNull::dangling());
assert_eq!(head.tag(), HeadTag::Leaf);
mem::forget(head);
}
#[test]
fn head_key() {
for k in 0..=255 {
let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(k, NonNull::dangling());
assert_eq!(head.key(), k);
mem::forget(head);
}
}
#[test]
fn head_size() {
assert_eq!(mem::size_of::<Head<64, IdentitySchema, ()>>(), 8);
}
#[test]
fn option_head_size() {
assert_eq!(mem::size_of::<Option<Head<64, IdentitySchema, ()>>>(), 8);
}
#[test]
fn empty_tree() {
let _tree = PATCH::<64, IdentitySchema, ()>::new();
}
#[test]
fn tree_put_one() {
const KEY_SIZE: usize = 64;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
let entry = Entry::new(&[0; KEY_SIZE]);
tree.insert(&entry);
}
#[test]
fn tree_clone_one() {
const KEY_SIZE: usize = 64;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
let entry = Entry::new(&[0; KEY_SIZE]);
tree.insert(&entry);
let _clone = tree.clone();
}
#[test]
fn tree_put_same() {
const KEY_SIZE: usize = 64;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
let entry = Entry::new(&[0; KEY_SIZE]);
tree.insert(&entry);
tree.insert(&entry);
}
#[test]
fn tree_replace_existing() {
const KEY_SIZE: usize = 64;
let key = [1u8; KEY_SIZE];
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let entry1 = Entry::with_value(&key, 1);
tree.insert(&entry1);
let entry2 = Entry::with_value(&key, 2);
tree.replace(&entry2);
assert_eq!(tree.get(&key), Some(&2));
}
#[test]
fn tree_replace_childleaf_updates_branch() {
const KEY_SIZE: usize = 64;
let key1 = [0u8; KEY_SIZE];
let key2 = [1u8; KEY_SIZE];
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let entry1 = Entry::with_value(&key1, 1);
let entry2 = Entry::with_value(&key2, 2);
tree.insert(&entry1);
tree.insert(&entry2);
let entry1b = Entry::with_value(&key1, 3);
tree.replace(&entry1b);
assert_eq!(tree.get(&key1), Some(&3));
assert_eq!(tree.get(&key2), Some(&2));
}
#[test]
fn update_child_refreshes_childleaf_on_replace() {
const KEY_SIZE: usize = 4;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let key1 = [0u8; KEY_SIZE];
let key2 = [1u8; KEY_SIZE];
tree.insert(&Entry::with_value(&key1, 1));
tree.insert(&Entry::with_value(&key2, 2));
let root_ref = tree.root.as_ref().expect("root exists");
let before_childleaf = *root_ref.childleaf_key();
let slot_key = match root_ref.body_ref() {
BodyRef::Branch(branch) => branch
.child_table
.iter()
.filter_map(|c| c.as_ref())
.find(|c| c.childleaf_key() == &before_childleaf)
.expect("child exists")
.key(),
BodyRef::Leaf(_) => panic!("root should be a branch"),
};
let new_key = [2u8; KEY_SIZE];
{
let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
ed.modify_child(slot_key, |_| {
Some(Entry::with_value(&new_key, 42).leaf::<IdentitySchema>())
});
}
let after = tree.root.as_ref().expect("root exists");
assert_eq!(after.childleaf_key(), &new_key);
}
#[test]
fn remove_childleaf_updates_branch() {
const KEY_SIZE: usize = 4;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let key1 = [0u8; KEY_SIZE];
let key2 = [1u8; KEY_SIZE];
tree.insert(&Entry::with_value(&key1, 1));
tree.insert(&Entry::with_value(&key2, 2));
let childleaf_before = *tree.root.as_ref().unwrap().childleaf_key();
tree.remove(&childleaf_before);
let other = if childleaf_before == key1 { key2 } else { key1 };
assert_eq!(tree.get(&childleaf_before), None);
assert_eq!(tree.get(&other), Some(&2u32));
let after_childleaf = tree.root.as_ref().unwrap().childleaf_key();
assert_eq!(after_childleaf, &other);
}
#[test]
fn remove_collapses_branch_to_single_child() {
const KEY_SIZE: usize = 4;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let key1 = [0u8; KEY_SIZE];
let key2 = [1u8; KEY_SIZE];
tree.insert(&Entry::with_value(&key1, 1));
tree.insert(&Entry::with_value(&key2, 2));
tree.remove(&key1);
assert_eq!(tree.get(&key1), None);
assert_eq!(tree.get(&key2), Some(&2u32));
let root = tree.root.as_ref().expect("root exists");
match root.body_ref() {
BodyRef::Leaf(_) => {}
BodyRef::Branch(_) => panic!("root should have collapsed to a leaf"),
}
}
#[test]
fn branch_size() {
assert_eq!(
mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 2], ()>>(
),
64
);
assert_eq!(
mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 4], ()>>(
),
48 + 16 * 2
);
assert_eq!(
mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 8], ()>>(
),
48 + 16 * 4
);
assert_eq!(
mem::size_of::<
Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 16], ()>,
>(),
48 + 16 * 8
);
assert_eq!(
mem::size_of::<
Branch<64, IdentitySchema, [Option<Head<32, IdentitySchema, ()>>; 32], ()>,
>(),
48 + 16 * 16
);
assert_eq!(
mem::size_of::<
Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 64], ()>,
>(),
48 + 16 * 32
);
assert_eq!(
mem::size_of::<
Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 128], ()>,
>(),
48 + 16 * 64
);
assert_eq!(
mem::size_of::<
Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 256], ()>,
>(),
48 + 16 * 128
);
}
#[test]
fn tree_union_single() {
const KEY_SIZE: usize = 8;
let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
let left_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 0]);
let right_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 1]);
left.insert(&left_entry);
right.insert(&right_entry);
left.union(right);
assert_eq!(left.len(), 2);
}
proptest! {
#[test]
fn tree_insert(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
let mut tree = PATCH::<64, IdentitySchema, ()>::new();
for key in keys {
let key: [u8; 64] = key.try_into().unwrap();
let entry = Entry::new(&key);
tree.insert(&entry);
}
}
#[test]
fn tree_len(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
let mut tree = PATCH::<64, IdentitySchema, ()>::new();
let mut set = HashSet::new();
for key in keys {
let key: [u8; 64] = key.try_into().unwrap();
let entry = Entry::new(&key);
tree.insert(&entry);
set.insert(key);
}
prop_assert_eq!(set.len() as u64, tree.len())
}
#[test]
fn tree_infixes(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
let mut tree = PATCH::<64, IdentitySchema, ()>::new();
let mut set = HashSet::new();
for key in keys {
let key: [u8; 64] = key.try_into().unwrap();
let entry = Entry::new(&key);
tree.insert(&entry);
set.insert(key);
}
let mut set_vec = Vec::from_iter(set.into_iter());
let mut tree_vec = vec![];
tree.infixes(&[0; 0], &mut |&x: &[u8; 64]| tree_vec.push(x));
set_vec.sort();
tree_vec.sort();
prop_assert_eq!(set_vec, tree_vec);
}
#[test]
fn tree_iter(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
let mut tree = PATCH::<64, IdentitySchema, ()>::new();
let mut set = HashSet::new();
for key in keys {
let key: [u8; 64] = key.try_into().unwrap();
let entry = Entry::new(&key);
tree.insert(&entry);
set.insert(key);
}
let mut set_vec = Vec::from_iter(set.into_iter());
let mut tree_vec = vec![];
for key in &tree {
tree_vec.push(*key);
}
set_vec.sort();
tree_vec.sort();
prop_assert_eq!(set_vec, tree_vec);
}
#[test]
fn tree_union(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200),
right in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200)) {
let mut set = HashSet::new();
let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
for entry in left {
let mut key = [0; 64];
key.iter_mut().set_from(entry.iter().cloned());
let entry = Entry::new(&key);
left_tree.insert(&entry);
set.insert(key);
}
let mut right_tree = PATCH::<64, IdentitySchema, ()>::new();
for entry in right {
let mut key = [0; 64];
key.iter_mut().set_from(entry.iter().cloned());
let entry = Entry::new(&key);
right_tree.insert(&entry);
set.insert(key);
}
left_tree.union(right_tree);
let mut set_vec = Vec::from_iter(set.into_iter());
let mut tree_vec = vec![];
left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
set_vec.sort();
tree_vec.sort();
prop_assert_eq!(set_vec, tree_vec);
}
#[test]
fn tree_union_empty(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 2)) {
let mut set = HashSet::new();
let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
for entry in left {
let mut key = [0; 64];
key.iter_mut().set_from(entry.iter().cloned());
let entry = Entry::new(&key);
left_tree.insert(&entry);
set.insert(key);
}
let right_tree = PATCH::<64, IdentitySchema, ()>::new();
left_tree.union(right_tree);
let mut set_vec = Vec::from_iter(set.into_iter());
let mut tree_vec = vec![];
left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
set_vec.sort();
tree_vec.sort();
prop_assert_eq!(set_vec, tree_vec);
}
#[test]
fn cow_on_insert(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
let mut tree = PATCH::<8, IdentitySchema, ()>::new();
for key in base_keys {
let key: [u8; 8] = key[..].try_into().unwrap();
let entry = Entry::new(&key);
tree.insert(&entry);
}
let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
let mut tree_clone = tree.clone();
for key in new_keys {
let key: [u8; 8] = key[..].try_into().unwrap();
let entry = Entry::new(&key);
tree_clone.insert(&entry);
}
let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
prop_assert_eq!(base_tree_content, new_tree_content);
}
#[test]
fn cow_on_union(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
let mut tree = PATCH::<8, IdentitySchema, ()>::new();
for key in base_keys {
let key: [u8; 8] = key[..].try_into().unwrap();
let entry = Entry::new(&key);
tree.insert(&entry);
}
let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
let mut tree_clone = tree.clone();
let mut new_tree = PATCH::<8, IdentitySchema, ()>::new();
for key in new_keys {
let key: [u8; 8] = key[..].try_into().unwrap();
let entry = Entry::new(&key);
new_tree.insert(&entry);
}
tree_clone.union(new_tree);
let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
prop_assert_eq!(base_tree_content, new_tree_content);
}
}
#[test]
fn intersect_multiple_common_children_commits_branchmut() {
const KEY_SIZE: usize = 4;
let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let a = [0u8, 0u8, 0u8, 1u8];
let b = [0u8, 0u8, 0u8, 2u8];
let c = [0u8, 0u8, 0u8, 3u8];
let d = [2u8, 0u8, 0u8, 0u8];
let e = [3u8, 0u8, 0u8, 0u8];
left.insert(&Entry::with_value(&a, 1));
left.insert(&Entry::with_value(&b, 2));
left.insert(&Entry::with_value(&c, 3));
left.insert(&Entry::with_value(&d, 4));
right.insert(&Entry::with_value(&a, 10));
right.insert(&Entry::with_value(&b, 11));
right.insert(&Entry::with_value(&c, 12));
right.insert(&Entry::with_value(&e, 13));
let res = left.intersect(&right);
assert_eq!(res.len(), 3);
assert!(res.get(&a).is_some());
assert!(res.get(&b).is_some());
assert!(res.get(&c).is_some());
}
#[test]
fn difference_multiple_children_commits_branchmut() {
const KEY_SIZE: usize = 4;
let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let a = [0u8, 0u8, 0u8, 1u8];
let b = [0u8, 0u8, 0u8, 2u8];
let c = [0u8, 0u8, 0u8, 3u8];
let d = [2u8, 0u8, 0u8, 0u8];
let e = [3u8, 0u8, 0u8, 0u8];
left.insert(&Entry::with_value(&a, 1));
left.insert(&Entry::with_value(&b, 2));
left.insert(&Entry::with_value(&c, 3));
left.insert(&Entry::with_value(&d, 4));
right.insert(&Entry::with_value(&a, 10));
right.insert(&Entry::with_value(&b, 11));
right.insert(&Entry::with_value(&c, 12));
right.insert(&Entry::with_value(&e, 13));
let res = left.difference(&right);
assert_eq!(res.len(), 1);
assert!(res.get(&d).is_some());
}
#[test]
fn difference_empty_left_is_empty() {
const KEY_SIZE: usize = 4;
let left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let key = [1u8, 2u8, 3u8, 4u8];
right.insert(&Entry::with_value(&key, 7));
let res = left.difference(&right);
assert_eq!(res.len(), 0);
}
#[test]
fn difference_empty_right_returns_left() {
const KEY_SIZE: usize = 4;
let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let key = [1u8, 2u8, 3u8, 4u8];
left.insert(&Entry::with_value(&key, 7));
let res = left.difference(&right);
assert_eq!(res.len(), 1);
assert!(res.get(&key).is_some());
}
#[test]
fn slot_edit_branchmut_insert_update() {
const KEY_SIZE: usize = 8;
let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
let entry1 = Entry::with_value(&[0u8; KEY_SIZE], 1u32);
let entry2 = Entry::with_value(&[1u8; KEY_SIZE], 2u32);
tree.insert(&entry1);
tree.insert(&entry2);
assert_eq!(tree.len(), 2);
{
let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
let start_depth = ed.end_depth as usize;
let inserted = Entry::with_value(&[2u8; KEY_SIZE], 3u32)
.leaf::<IdentitySchema>()
.with_start(start_depth);
let key = inserted.key();
ed.modify_child(key, |opt| match opt {
Some(old) => Some(Head::insert_leaf(old, inserted, start_depth)),
None => Some(inserted),
});
}
assert_eq!(tree.len(), 3);
assert_eq!(tree.get(&[2u8; KEY_SIZE]), Some(&3u32));
}
}