use std::collections::BTreeMap;
use std::sync::Arc;
use crate::persistent_artrie_core::key_encoding::KeyEncoding;
use crate::persistent_artrie_core::overlay::node::{Child, OverlayNode};
use crate::value::DictionaryValue;
struct OverlayBuilderNode<K: KeyEncoding, V> {
is_final: bool,
value: Option<V>,
children: BTreeMap<K::Unit, Box<OverlayBuilderNode<K, V>>>,
}
impl<K: KeyEncoding, V> OverlayBuilderNode<K, V> {
fn new() -> Self {
Self {
is_final: false,
value: None,
children: BTreeMap::new(),
}
}
}
impl<K: KeyEncoding, V> Drop for OverlayBuilderNode<K, V> {
fn drop(&mut self) {
let mut worklist: Vec<Box<OverlayBuilderNode<K, V>>> = Vec::new();
for (_, child) in std::mem::take(&mut self.children) {
worklist.push(child);
}
while let Some(mut node) = worklist.pop() {
for (_, child) in std::mem::take(&mut node.children) {
worklist.push(child);
}
}
}
}
pub(crate) fn build_overlay_root_from_terms<K, V, I>(
terms: I,
empty_term: Option<Option<V>>,
) -> Arc<OverlayNode<K, V>>
where
K: KeyEncoding,
V: DictionaryValue,
I: IntoIterator<Item = (Vec<K::Unit>, Option<V>)>,
{
let mut root = OverlayBuilderNode::<K, V>::new();
if let Some(empty_value) = empty_term {
root.is_final = true;
root.value = empty_value; }
for (units, value) in terms {
let mut cur = &mut root;
for unit in units {
cur = cur
.children
.entry(unit)
.or_insert_with(|| Box::new(OverlayBuilderNode::<K, V>::new()));
}
cur.is_final = true;
if value.is_some() {
cur.value = value;
}
}
convert_builder_to_overlay::<K, V>(root)
}
fn convert_builder_to_overlay<K, V>(root: OverlayBuilderNode<K, V>) -> Arc<OverlayNode<K, V>>
where
K: KeyEncoding,
V: DictionaryValue,
{
struct Pending<K: KeyEncoding, V: DictionaryValue> {
edge: K::Unit,
built: Option<Arc<OverlayNode<K, V>>>,
}
struct Frame<K: KeyEncoding, V: DictionaryValue> {
is_final: bool,
value: Option<V>,
parent_edge: Option<K::Unit>,
pending_children: Vec<(K::Unit, Box<OverlayBuilderNode<K, V>>)>,
slots: Vec<Pending<K, V>>,
}
fn make_frame<K: KeyEncoding, V: DictionaryValue>(
mut node: Box<OverlayBuilderNode<K, V>>,
parent_edge: Option<K::Unit>,
) -> Frame<K, V> {
let mut pending_children: Vec<(K::Unit, Box<OverlayBuilderNode<K, V>>)> =
std::mem::take(&mut node.children).into_iter().collect();
let mut slots: Vec<Pending<K, V>> = Vec::with_capacity(pending_children.len());
for (edge, _) in &pending_children {
slots.push(Pending {
edge: *edge,
built: None,
});
}
pending_children.reverse(); Frame {
is_final: node.is_final,
value: node.value.take(),
parent_edge,
pending_children,
slots,
}
}
let mut stack: Vec<Frame<K, V>> = Vec::new();
stack.push(make_frame(Box::new(root), None));
let mut completed: Option<(K::Unit, Arc<OverlayNode<K, V>>)> = None;
loop {
let frame = stack
.last_mut()
.expect("F5 builder→overlay: non-empty work-stack");
if let Some((edge, built)) = completed.take() {
let slot = frame
.slots
.iter_mut()
.find(|s| s.edge == edge && s.built.is_none())
.expect("F5 builder→overlay: completed child edge has an unfilled parent slot");
slot.built = Some(built);
}
if let Some((edge, child)) = frame.pending_children.pop() {
stack.push(make_frame(child, Some(edge)));
continue;
}
let frame = stack.pop().expect("F5 builder→overlay: frame to finalize");
let mut node = OverlayNode::<K, V>::new();
if frame.is_final {
node = node.as_final();
}
if let Some(v) = frame.value {
node = node.with_value(v);
}
for slot in frame.slots {
let built = slot.built.expect(
"F5 builder→overlay: every child slot is filled before its parent is built \
(post-order invariant)",
);
node = node.with_child(slot.edge, Child::InMem(built));
}
let node_arc = Arc::new(node);
match frame.parent_edge {
Some(edge) => completed = Some((edge, node_arc)),
None => return node_arc,
}
}
}