Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/trie_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2682,8 +2682,12 @@ where
/// Ensures the node is a CellByteNode
///
/// Returns `true` if the node was upgraded and `false` if it already was a CellByteNode
pub(crate) fn make_cell_node<V: Clone + Send + Sync, A: Allocator>(node: &mut TrieNodeODRc<V, A>) -> bool {
if !node.as_tagged().is_cell_node() {
pub(crate) fn make_cell_node<V: Clone + Send + Sync, A: Allocator>(node: &mut TrieNodeODRc<V, A>, alloc: A) -> bool {
if node.is_empty() {
//The empty sentinel can't be made mutable; there is nothing in it to keep
*node = TrieNodeODRc::new_in(crate::dense_byte_node::CellByteNode::new_in(alloc.clone()), alloc);
true
} else if !node.as_tagged().is_cell_node() {
let replacement = node.make_mut().convert_to_cell_node();
*node = replacement;
true
Expand Down
44 changes: 38 additions & 6 deletions src/zipper_head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ pub(crate) fn prepare_exclusive_write_path<'a, 'trie: 'a, 'path: 'a, V: Clone +
debug_assert_eq!(z.focus_stack.depth(), 1);
z.focus_stack.to_root();
let stack_root = z.focus_stack.root_mut().unwrap();
make_cell_node(stack_root);
make_cell_node(stack_root, z.alloc.clone());
let root_val = z.root_val.as_mut().unwrap();
return (stack_root, unsafe{ &mut **root_val })
}
Expand Down Expand Up @@ -386,7 +386,7 @@ pub(crate) fn prepare_exclusive_write_path<'a, 'trie: 'a, 'path: 'a, V: Clone +
|node, key| {
let new_node = if key.len() > 0 {
if let Some(mut remaining) = node.take_node_at_key(key, false) {
make_cell_node(&mut remaining);
make_cell_node(&mut remaining, alloc.clone());
remaining
} else {
TrieNodeODRc::new_in(CellByteNode::new_in(alloc.clone()), alloc)
Expand Down Expand Up @@ -419,8 +419,9 @@ pub(crate) fn prepare_exclusive_write_path<'a, 'trie: 'a, 'path: 'a, V: Clone +

//If the node on top of the stack is not a cell node, we need to upgrade it
if !z.focus_stack.top().unwrap().is_cell_node() {
let alloc = z.alloc.clone();
swap_top_node(&mut z.focus_stack, &z.key, |mut existing_node| {
make_cell_node(&mut existing_node);
make_cell_node(&mut existing_node, alloc);
existing_node
});
}
Expand All @@ -439,9 +440,9 @@ fn prepare_node_at_path_end<'a, V: Clone + Send + Sync, A: Allocator>(start_node
let mut node_ref = node.make_mut();
let mut new_parent = match node_ref.take_node_at_key(remaining_key, false) {
Some(downward_node) => downward_node,
None => TrieNodeODRc::new_in(CellByteNode::new_in(alloc.clone()), alloc)
None => TrieNodeODRc::new_in(CellByteNode::new_in(alloc.clone()), alloc.clone())
};
make_cell_node(&mut new_parent);
make_cell_node(&mut new_parent, alloc.clone());
let result = node_ref.node_set_branch(remaining_key, new_parent);
match result {
Ok(_) => { },
Expand All @@ -452,7 +453,7 @@ fn prepare_node_at_path_end<'a, V: Clone + Send + Sync, A: Allocator>(start_node
node = child_node;
} else {
//Otherwise just upgrade node
make_cell_node(node);
make_cell_node(node, alloc);
}
node
}
Expand Down Expand Up @@ -1605,4 +1606,35 @@ mod tests {
assert_eq!(map.val_at(&[1u8, 9, 5]), Some(&3));
assert_eq!(map.val_count(), 7);
}

/// Exclusive paths from a head whose focus node is the empty sentinel
#[test]
fn exclusive_path_over_empty_node() {
let setups: [fn(&mut PathMap<u64>); 3] = [
|m| { m.write_zipper_at_path(&[0u8, 0]).remove_branches(false); },
|m| { let e = PathMap::<u64>::new(); m.write_zipper_at_path(&[0u8, 0]).graft(&e.read_zipper()); },
|m| { m.write_zipper_at_path(&[0u8, 0]).take_map(false); },
];
for (i, setup) in setups.iter().enumerate() {
for paths in [[&[][..], &[5u8][..]], [&[5u8, 6][..], &[][..]], [&[0u8, 0][..], &[1u8][..]]] {
let mut map = PathMap::<u64>::new();
map.set_val_at(&[0u8, 0, 1, 2], 9);
map.set_val_at(&[7u8], 9);
setup(&mut map);
{
let mut wz = map.write_zipper_at_path(&[0u8, 0]);
let zh = wz.zipper_head();
for (n, p) in paths.iter().enumerate() {
let mut w = zh.write_zipper_at_exclusive_path(p).unwrap();
w.set_val(n as u64);
}
}
assert_eq!(map.val_at(&[7u8]), Some(&9), "setup {i} {paths:?}");
for (n, p) in paths.iter().enumerate() {
let full: Vec<u8> = [&[0u8, 0][..], p].concat();
assert_eq!(map.val_at(&full), Some(&(n as u64)), "setup {i} {paths:?}");
}
}
}
}
}