Skip to content
Merged
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
34 changes: 32 additions & 2 deletions src/zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,9 +1119,10 @@ fn k_path_default_internal<Z: ZipperMoving + ?Sized, Obs: PathObserver>(z: &mut
if z.depth() == base_idx + k { return true }
}
}
//A sibling step replaces the last byte rather than adding one, so the observer sees the old
//byte retracted before the new one arrives
if z.depth() == base_idx { return false }
if let Some(byte) = z.to_next_sibling_byte() {
//A sibling step replaces the last byte rather than adding one, so the observer sees the old
//byte retracted before the new one arrives
obs.ascend(1);
obs.descend_to_byte(byte);
if z.depth() == base_idx + k { return true }
Expand Down Expand Up @@ -4817,6 +4818,22 @@ pub(crate) mod zipper_iteration_tests {
crate::zipper::zipper_iteration_tests::run_test(&mut temp_store, $make_z, b"", crate::zipper::zipper_iteration_tests::k_path_zero)
}

#[test]
fn [<$z_name _k_path_walk_at_a_leaf>]() {
use crate::zipper::zipper_iteration_tests::{k_path_walk_at_a_leaf, run_test};
const LEAF_KEYS: &[&[u8]] = &[&[1u8]];
for (keys, path, has_child) in [
(&[][..], &[][..], false),
(LEAF_KEYS, &[1u8][..], false),
(LEAF_KEYS, &[][..], true),
] {
let mut temp_store = $read_keys(keys);
run_test(&mut temp_store, $make_z, b"", |zipper| {
k_path_walk_at_a_leaf(zipper, path, has_child)
});
}
}

#[test]
fn [<$z_name _k_path_test2>]() {
let paths = crate::zipper::zipper_iteration_tests::k_path_test2_paths();
Expand Down Expand Up @@ -4942,6 +4959,19 @@ pub(crate) mod zipper_iteration_tests {
assert_eq!(zipper.path(), b"a");
}

/// A k-path walk must stop at an empty root or leaf without stepping to a sibling.
pub fn k_path_walk_at_a_leaf<Z: ZipperIteration + ZipperPath>(mut zipper: Z, path: &[u8], has_child: bool) {
for k in 0..3 {
zipper.reset();
zipper.descend_to(path);
let found = zipper.descend_first_k_path(k);
assert_eq!(found, has_child && k == 1, "{path:?} k={k}");
if !found {
assert_eq!(zipper.path(), path, "{path:?} k={k}");
}
}
}

/// This is a toy encoding where `:n:` precedes a symbol `n` characters long
pub const K_PATH_TEST1_KEYS: &[&[u8]] = &[
b":5:above:3:the:4:fray:",
Expand Down