use crate::utils::{Length, MaybeArced, opt_packing_depth, opt_packing_factor};
use crate::{Arc, Error, MAX_TREE_DEPTH, PackedLeaf, Tree, Value};
#[derive(Debug)]
pub struct Builder<T: Value> {
stack: Vec<MaybeArced<Tree<T>>>,
depth: usize,
level: usize,
length: Length,
packing_factor: Option<usize>,
packing_depth: usize,
capacity: usize,
}
impl<T: Value> Builder<T> {
pub fn new(depth: usize, level: usize) -> Result<Self, Error> {
let packing_depth = opt_packing_depth::<T>().unwrap_or(0);
if depth.saturating_add(packing_depth) > MAX_TREE_DEPTH {
Err(Error::BuilderInvalidDepth { depth })
} else {
let capacity = 1 << (depth + packing_depth);
Ok(Self {
stack: Vec::with_capacity(depth),
depth,
level,
length: Length(0),
packing_factor: opt_packing_factor::<T>(),
packing_depth,
capacity,
})
}
}
pub fn push(&mut self, value: T) -> Result<(), Error> {
if self.length.as_usize() == self.capacity {
return Err(Error::BuilderFull);
}
let index = self.length.as_usize();
let next_index = index + 1;
let mut new_stack_top = if let Some(packing_factor) = self.packing_factor {
if index.is_multiple_of(packing_factor) {
MaybeArced::Unarced(Tree::PackedLeaf(PackedLeaf::single(value)))
} else if let Some(MaybeArced::Unarced(Tree::PackedLeaf(mut leaf))) = self.stack.pop() {
leaf.push(value)?;
MaybeArced::Unarced(Tree::PackedLeaf(leaf))
} else {
return Err(Error::BuilderExpectedLeaf);
}
} else {
MaybeArced::Unarced(Tree::leaf_unboxed(value))
};
let values_to_merge = next_index
.trailing_zeros()
.saturating_sub(self.packing_depth as u32);
for _ in 0..values_to_merge {
let left = self.stack.pop().ok_or(Error::BuilderStackEmptyMerge)?;
new_stack_top =
MaybeArced::Unarced(Tree::node_unboxed(left.arced(), new_stack_top.arced()));
}
self.stack.push(new_stack_top);
*self.length.as_mut() += 1;
Ok(())
}
pub fn push_node(&mut self, node: Arc<Tree<T>>, len: usize) -> Result<(), Error> {
if self.length.as_usize() == self.capacity {
return Err(Error::BuilderFull);
}
let index_on_level = self.length.as_usize() >> self.level;
let next_index_on_level = index_on_level + 1;
let mut new_stack_top = MaybeArced::Arced(node);
let values_to_merge = if self.level == 0 {
next_index_on_level
.trailing_zeros()
.saturating_sub(self.packing_depth as u32)
} else {
next_index_on_level.trailing_zeros()
};
for _ in 0..values_to_merge {
if let Some(left) = self.stack.pop() {
new_stack_top =
MaybeArced::Unarced(Tree::node_unboxed(left.arced(), new_stack_top.arced()));
}
}
self.stack.push(new_stack_top);
*self.length.as_mut() += len;
Ok(())
}
pub fn finish(mut self) -> Result<(Arc<Tree<T>>, usize, Length), Error> {
if self.stack.is_empty() {
return Ok((Tree::zero(self.depth), self.depth, Length(0)));
}
let length = self.length.as_usize();
let level_capacity = 1 << self.level;
let mut next_index_on_level = length.div_ceil(level_capacity);
if let Some(packing_factor) = self.packing_factor {
let skip_indices = packing_factor
.saturating_sub(self.length.as_usize() % packing_factor)
% packing_factor;
if skip_indices > 0 && self.level == 0 {
for i in 0..self.depth {
if (next_index_on_level >> (i + self.packing_depth)) & 1 == 1 {
let right = self.stack.pop().ok_or(Error::BuilderStackEmptyMergeRight)?;
let left = self.stack.pop().ok_or(Error::BuilderStackEmptyMergeLeft)?;
self.stack.push(MaybeArced::Unarced(Tree::node_unboxed(
left.arced(),
right.arced(),
)));
} else {
break;
}
}
next_index_on_level += skip_indices;
}
}
while next_index_on_level << self.level != self.capacity {
let depth = (next_index_on_level.trailing_zeros() as usize)
.saturating_add(self.level)
.saturating_sub(self.packing_depth);
let stack_top = self.stack.pop().ok_or(Error::BuilderStackEmptyFinish)?;
let new_stack_top =
MaybeArced::Unarced(Tree::node_unboxed(stack_top.arced(), Tree::zero(depth)));
self.stack.push(new_stack_top);
for i in depth + 1..self.depth {
if ((next_index_on_level << self.level) >> (i + self.packing_depth)) & 1 == 1 {
let right = self
.stack
.pop()
.ok_or(Error::BuilderStackEmptyFinishRight)?;
let left = self.stack.pop().ok_or(Error::BuilderStackEmptyFinishLeft)?;
self.stack.push(MaybeArced::Unarced(Tree::node_unboxed(
left.arced(),
right.arced(),
)));
} else {
break;
}
}
next_index_on_level += 2usize.pow((depth + self.packing_depth - self.level) as u32);
}
let tree = self
.stack
.pop()
.ok_or(Error::BuilderStackEmptyFinalize)?
.arced();
if !self.stack.is_empty() {
return Err(Error::BuilderStackLeftover);
}
Ok((tree, self.depth, self.length))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn depth_upper_limit() {
assert_eq!(
Builder::<u64>::new(62, 0).unwrap_err(),
Error::BuilderInvalidDepth { depth: 62 }
);
assert_eq!(Builder::<u64>::new(61, 0).unwrap().depth, 61);
}
}