diff --git a/src/product_zipper.rs b/src/product_zipper.rs index d437163e..ff06bbcd 100644 --- a/src/product_zipper.rs +++ b/src/product_zipper.rs @@ -270,6 +270,8 @@ impl<'trie, V: Clone + Send + Sync + Unpin + 'trie, A: Allocator + 'trie> Zipper //Stepping sideways leaves a factor entered at this depth. if self.factor_paths.last().cloned() == Some(self.depth()) { self.factor_paths.pop(); + self.z.deregularize(); + self.z.regularize(); } let moved = self.z.to_next_sibling_byte(); self.ensure_descend_next_factor(); @@ -280,6 +282,8 @@ impl<'trie, V: Clone + Send + Sync + Unpin + 'trie, A: Allocator + 'trie> Zipper //Stepping sideways leaves a factor entered at this depth. if self.factor_paths.last().cloned() == Some(self.depth()) { self.factor_paths.pop(); + self.z.deregularize(); + self.z.regularize(); } let moved = self.z.to_prev_sibling_byte(); self.ensure_descend_next_factor(); @@ -2041,6 +2045,45 @@ mod tests { ProductZipperG::new::<[ReadZipperUntracked<()>; 0]>(btm.read_zipper_at_path(path), []) }); + /// A failed sibling step at the root of a factor stays in that factor + #[test] + fn product_zipper_no_sibling_at_factor_root() { + let mut a = PathMap::::new(); + a.set_val_at(&[0u8, 0], 1); + let mut b = PathMap::::new(); + b.set_val_at(&[5u8], 2); + for prev in [false, true] { + let mut z = ProductZipper::new(a.read_zipper(), [b.read_zipper()]); + assert!(z.to_next_val()); + assert_eq!(z.path(), &[0, 0]); + let moved = if prev { z.to_prev_sibling_byte() } else { z.to_next_sibling_byte() }; + assert_eq!(moved, None); + assert_eq!(z.child_count(), 1); + let _ = (z.is_shared(), z.shared_node_id()); + assert!(z.to_next_val()); + assert_eq!((z.path(), z.val()), (&[0u8, 0, 5][..], Some(&2))); + } + } + + /// Sibling steps out of a factor entered below an empty node, as a dropped head writer leaves + #[test] + fn product_zipper_k_path_past_empty_node() { + let mut a = PathMap::::new(); + for p in [&[0u8][..], &[0, 0, 0], &[1]] { a.set_val_at(p, 0); } + { + let zh = a.zipper_head(); + zh.write_zipper_at_exclusive_path(&[1u8, 0]).unwrap().set_val(0); + let _w = zh.write_zipper_at_exclusive_path(&[0u8, 0, 0, 0]).unwrap(); + } + let b = a.clone(); + let mut z = ProductZipper::new(a.read_zipper(), [b.read_zipper()]); + let mut paths = vec![]; + if z.descend_first_k_path(3) { + paths.push(z.path().to_vec()); + while paths.len() < 64 && z.to_next_k_path(3) { paths.push(z.path().to_vec()); } + } + assert!(paths.iter().all(|p| p.len() == 3), "{paths:?}"); + } } //POSSIBLE FUTURE DIRECTION: