Skip to content
Open
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
4 changes: 2 additions & 2 deletions benches/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ fn parallel_copy_traverse(bencher: Bencher, (elements, thread_cnt): (usize, &str
Ok((mut reader_z, mut writer_z)) => {
//We got the zippers, do the stuff
let witness = reader_z.witness();
while let Some(val) = reader_z.to_next_get_val_with_witness(&witness) {
while let Some(val) = reader_z.to_next_get_val_with_witness(&witness, &mut ()) {
writer_z.move_to_path(reader_z.path());
writer_z.set_val(*val);

Expand Down Expand Up @@ -363,7 +363,7 @@ fn parallel_copy_traverse(bencher: Bencher, (elements, thread_cnt): (usize, &str
let mut writer_z = unsafe{ zipper_head.write_zipper_at_exclusive_path_unchecked(&[b'o', b'u', b't', 0]) };
let mut reader_z = unsafe{ zipper_head.read_zipper_at_path_unchecked(&[b'i', b'n', 0]) };
let witness = reader_z.witness();
while let Some(val) = reader_z.to_next_get_val_with_witness(&witness) {
while let Some(val) = reader_z.to_next_get_val_with_witness(&witness, &mut ()) {
writer_z.move_to_path(reader_z.path());
writer_z.set_val(*val);
sanity_counter += 1;
Expand Down
71 changes: 52 additions & 19 deletions pathmap-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum PolyZipperTrait {
ZipperMoving,
ZipperIteration,
ZipperConcrete,
ZipperPath,
ZipperAbsolutePath,
ZipperPathBuffer,
ZipperSubtries,
Expand All @@ -33,6 +34,7 @@ impl PolyZipperTrait {
"ZipperMoving" => Some(Self::ZipperMoving),
"ZipperIteration" => Some(Self::ZipperIteration),
"ZipperConcrete" => Some(Self::ZipperConcrete),
"ZipperPath" => Some(Self::ZipperPath),
"ZipperAbsolutePath" => Some(Self::ZipperAbsolutePath),
"ZipperPathBuffer" => Some(Self::ZipperPathBuffer),
"ZipperSubtries" => Some(Self::ZipperSubtries),
Expand All @@ -54,6 +56,7 @@ fn all_poly_zipper_traits() -> BTreeSet<PolyZipperTrait> {
ZipperMoving,
ZipperIteration,
ZipperConcrete,
ZipperPath,
ZipperAbsolutePath,
ZipperPathBuffer,
ZipperSubtries,
Expand Down Expand Up @@ -98,6 +101,11 @@ fn add_trait_dependencies(traits: &mut BTreeSet<PolyZipperTrait>) {
}
}
if traits.contains(&ZipperAbsolutePath) {
if traits.insert(ZipperPath) {
changed = true;
}
}
if traits.contains(&ZipperPath) {
if traits.insert(ZipperMoving) {
changed = true;
}
Expand Down Expand Up @@ -459,19 +467,16 @@ fn derive_poly_zipper_with_traits(
quote! {}
};
Some(quote! {
impl #impl_generics pathmap::zipper::ZipperPath for #enum_name #ty_generics
impl #impl_generics pathmap::zipper::ZipperMoving for #enum_name #ty_generics
#zipper_moving_where
{
fn path(&self) -> &[u8] {
#[inline]
fn depth(&self) -> usize {
match self {
#(#variant_arms => inner.path(),)*
#(#variant_arms => inner.depth(),)*
}
}
}

impl #impl_generics pathmap::zipper::ZipperMoving for #enum_name #ty_generics
#zipper_moving_where
{
fn at_root(&self) -> bool {
match self {
#(#variant_arms => inner.at_root(),)*
Expand Down Expand Up @@ -572,6 +577,33 @@ fn derive_poly_zipper_with_traits(
None
};

// Generate ZipperPath trait implementation
let zipper_path_impl = if traits.contains(&PolyZipperTrait::ZipperPath) {
let variant_arms = &variant_arms;
let zipper_path_where = if include_where_clause {
quote! {
where
#(#inner_types: pathmap::zipper::ZipperPath,)*
#where_clause
}
} else {
quote! {}
};
Some(quote! {
impl #impl_generics pathmap::zipper::ZipperPath for #enum_name #ty_generics
#zipper_path_where
{
fn path(&self) -> &[u8] {
match self {
#(#variant_arms => inner.path(),)*
}
}
}
})
} else {
None
};

// Generate ZipperAbsolutePath trait implementation
let zipper_absolute_path_impl = if traits.contains(&PolyZipperTrait::ZipperAbsolutePath) {
let variant_arms = &variant_arms;
Expand Down Expand Up @@ -660,27 +692,27 @@ fn derive_poly_zipper_with_traits(
impl #impl_generics pathmap::zipper::ZipperIteration for #enum_name #ty_generics
#zipper_iteration_where
{
fn to_next_val(&mut self) -> bool {
fn to_next_val_observed<Obs: pathmap::zipper::PathObserver>(&mut self, obs: &mut Obs) -> bool {
match self {
#(#variant_arms => inner.to_next_val(),)*
#(#variant_arms => inner.to_next_val_observed(obs),)*
}
}

fn descend_last_path(&mut self) -> bool {
fn descend_last_path_observed<Obs: pathmap::zipper::PathObserver>(&mut self, obs: &mut Obs) -> bool {
match self {
#(#variant_arms => inner.descend_last_path(),)*
#(#variant_arms => inner.descend_last_path_observed(obs),)*
}
}

fn descend_first_k_path(&mut self, k: usize) -> bool {
fn descend_first_k_path_observed<Obs: pathmap::zipper::PathObserver>(&mut self, k: usize, obs: &mut Obs) -> bool {
match self {
#(#variant_arms => inner.descend_first_k_path(k),)*
#(#variant_arms => inner.descend_first_k_path_observed(k, obs),)*
}
}

fn to_next_k_path(&mut self, k: usize) -> bool {
fn to_next_k_path_observed<Obs: pathmap::zipper::PathObserver>(&mut self, k: usize, obs: &mut Obs) -> bool {
match self {
#(#variant_arms => inner.to_next_k_path(k),)*
#(#variant_arms => inner.to_next_k_path_observed(k, obs),)*
}
}
}
Expand All @@ -705,9 +737,9 @@ fn derive_poly_zipper_with_traits(
impl #impl_generics pathmap::zipper::ZipperReadOnlyIteration<'trie, V> for #enum_name #ty_generics
#zipper_read_only_iteration_where
{
fn to_next_get_val(&mut self) -> Option<&'trie V> {
fn to_next_get_val_observed<Obs: pathmap::zipper::PathObserver>(&mut self, obs: &mut Obs) -> Option<&'trie V> {
match self {
#(#variant_arms => inner.to_next_get_val(),)*
#(#variant_arms => inner.to_next_get_val_observed(obs),)*
}
}
}
Expand All @@ -731,9 +763,9 @@ fn derive_poly_zipper_with_traits(
impl #impl_generics pathmap::zipper::ZipperReadOnlyConditionalIteration<'trie, V> for #enum_name #ty_generics
#zipper_read_only_conditional_iteration_where
{
fn to_next_get_val_with_witness<'w>(&mut self, witness: &'w Self::WitnessT) -> Option<&'w V> where 'trie: 'w {
fn to_next_get_val_with_witness_observed<'w, Obs: pathmap::zipper::PathObserver>(&mut self, witness: &'w Self::WitnessT, obs: &mut Obs) -> Option<&'w V> where 'trie: 'w {
match (self, witness) {
#((Self::#variant_names(inner), #witness_enum_name::#variant_names(w)) => inner.to_next_get_val_with_witness(w),)*
#((Self::#variant_names(inner), #witness_enum_name::#variant_names(w)) => inner.to_next_get_val_with_witness_observed(w, obs),)*
_ => {
debug_assert!(false, "Witness variant must match zipper variant");
None
Expand Down Expand Up @@ -847,6 +879,7 @@ fn derive_poly_zipper_with_traits(
// #zipper_forking_impl
#zipper_moving_impl
#zipper_concrete_impl
#zipper_path_impl
#zipper_absolute_path_impl
#zipper_path_buffer_impl
#zipper_iteration_impl
Expand Down
74 changes: 54 additions & 20 deletions src/arena_compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2892,6 +2892,9 @@ where Storage: AsRef<[u8]>
impl<'tree, Storage, Value> ZipperMoving for ACTZipper<'tree, Storage, Value>
where Storage: AsRef<[u8]>
{
#[inline]
fn depth(&self) -> usize { self.path.len().saturating_sub(self.origin_depth) }

/// Returns `true` if the zipper cannot ascend further, otherwise returns `false`
fn at_root(&self) -> bool { self.path.len() <= self.origin_depth }

Expand Down Expand Up @@ -3149,7 +3152,7 @@ where Storage: AsRef<[u8]>
}

// default
// fn to_next_step(&mut self) -> bool;
// fn to_next_step<Obs: PathObserver>(&mut self, obs: &mut Obs) -> bool;
}

impl<Storage, Value> ZipperIteration for ACTZipper<'_, Storage, Value>
Expand All @@ -3159,8 +3162,8 @@ where Storage: AsRef<[u8]>
/// order
///
/// Returns a reference to the value or `None` if the zipper has encountered the root.
fn to_next_val(&mut self) -> bool {
while self.to_next_step() {
fn to_next_val_observed<Obs: PathObserver>(&mut self, obs: &mut Obs) -> bool {
while self.to_next_step_observed(obs) {
if self.is_val() {
return true;
}
Expand All @@ -3178,11 +3181,15 @@ where Storage: AsRef<[u8]>
/// below the zipper's focus. Although a typical cost is `order log n` or better.
///
/// See: [to_next_k_path](ZipperIteration::to_next_k_path)
fn descend_first_k_path(&mut self, k: usize) -> bool {
fn descend_first_k_path_observed<Obs: PathObserver>(&mut self, k: usize, obs: &mut Obs) -> bool {
for ii in 0..k {
if self.descend_first_byte().is_none() {
self.ascend(ii);
return false;
match self.descend_first_byte() {
Some(byte) => obs.descend_to_byte(byte),
None => {
self.ascend(ii);
obs.ascend(ii);
return false;
}
}
}
return true;
Expand All @@ -3199,35 +3206,46 @@ where Storage: AsRef<[u8]>
/// below the zipper's focus. Although a typical cost is `order log n` or better.
///
/// See: [descend_first_k_path](ZipperIteration::descend_first_k_path)
fn to_next_k_path(&mut self, k: usize) -> bool {
fn to_next_k_path_observed<Obs: PathObserver>(&mut self, k: usize, obs: &mut Obs) -> bool {
let mut depth = k;
'outer: loop {
while depth > 0 && self.child_count() <= 1 {
if self.ascend(1) == 0 {
break 'outer;
}
obs.ascend(1);
depth -= 1;
}
let stack = self.stack.last_mut().unwrap();
let idx = stack.child_index + 1;
if idx >= stack.child_count {
if depth == 0 || self.ascend(1) == 0 {
if depth == 0 {
break 'outer;
}
if self.ascend(1) == 0 {
break 'outer;
}
obs.ascend(1);
depth -= 1;
continue 'outer;
}
assert!(self.descend_indexed_byte(idx).is_some());
//The loops above already ascended, so this is a plain descent of one byte
match self.descend_indexed_byte(idx) {
Some(byte) => obs.descend_to_byte(byte),
None => unreachable!("idx was bounds-checked against child_count above"),
}
depth += 1;
for _ii in 0..k - depth {
if self.descend_first_byte().is_none() {
continue 'outer;
match self.descend_first_byte() {
Some(byte) => obs.descend_to_byte(byte),
None => continue 'outer,
}
depth += 1;
}
return true;
}
self.ascend(depth);
obs.ascend(depth);
false
}
}
Expand Down Expand Up @@ -3326,14 +3344,18 @@ mod tests {
let mut btm_zipper = btm.read_zipper();
let mut act_zipper = act.read_zipper_u64();

let mut btm_observed = Vec::<u8>::new();
let mut act_observed = Vec::<u8>::new();
loop {
btm_zipper.to_next_val();
act_zipper.to_next_val();
btm_zipper.to_next_val_observed(&mut btm_observed);
act_zipper.to_next_val_observed(&mut act_observed);

let btm_val = btm_zipper.val().copied();
let act_val = act_zipper.val().copied();

assert_eq!(btm_zipper.path(), act_zipper.path());
assert_eq!(btm_observed, act_observed);
assert_eq!(&btm_observed[..], btm_zipper.path());
assert_eq!(btm_val, act_val);

if act_val.is_none() {
Expand Down Expand Up @@ -3641,11 +3663,15 @@ mod tests {
let btm = PathMap::from_iter(items.iter().map(|&(k, v)| (k, v)));
let mut bz = btm.read_zipper();
let mut az = act.read_zipper_u64();
let mut b_observed = Vec::<u8>::new();
let mut a_observed = Vec::<u8>::new();
loop {
let more_b = bz.to_next_val();
let more_a = az.to_next_val();
let more_b = bz.to_next_val_observed(&mut b_observed);
let more_a = az.to_next_val_observed(&mut a_observed);
assert_eq!(more_b, more_a, "walks end together");
assert_eq!(bz.path(), az.path());
assert_eq!(b_observed, a_observed);
assert_eq!(&b_observed[..], bz.path());
assert_eq!(bz.val().copied(), az.val().copied());
if !more_a {
break;
Expand Down Expand Up @@ -3826,11 +3852,15 @@ mod tests {
let act = ArenaCompactTree::from_zipper(btm.read_zipper(), |&v| v);
let mut cata_zipper = act.read_zipper_u64();
let mut stream_zipper = tree.read_zipper_u64();
let mut cata_observed = Vec::<u8>::new();
let mut stream_observed = Vec::<u8>::new();
loop {
let cata_next = cata_zipper.to_next_val();
let stream_next = stream_zipper.to_next_val();
let cata_next = cata_zipper.to_next_val_observed(&mut cata_observed);
let stream_next = stream_zipper.to_next_val_observed(&mut stream_observed);
assert_eq!(cata_next, stream_next);
assert_eq!(cata_zipper.path(), stream_zipper.path());
assert_eq!(cata_observed, stream_observed);
assert_eq!(&cata_observed[..], cata_zipper.path());
assert_eq!(cata_zipper.get_val(), stream_zipper.get_val());
if !cata_next {
break;
Expand Down Expand Up @@ -3948,10 +3978,14 @@ mod tests {
fn assert_act_matches_map(map: &PathMap<u64>, tree: &ArenaCompactTree<super::Mmap>) {
let mut map_zipper = map.read_zipper();
let mut act_zipper = tree.read_zipper_u64();
let mut map_observed = Vec::<u8>::new();
let mut act_observed = Vec::<u8>::new();
loop {
let map_next = map_zipper.to_next_val();
assert_eq!(map_next, act_zipper.to_next_val());
let map_next = map_zipper.to_next_val_observed(&mut map_observed);
assert_eq!(map_next, act_zipper.to_next_val_observed(&mut act_observed));
assert_eq!(map_zipper.path(), act_zipper.path());
assert_eq!(map_observed, act_observed);
assert_eq!(&map_observed[..], map_zipper.path());
assert_eq!(map_zipper.val().copied(), act_zipper.val().copied());
if !map_next { break }
}
Expand Down
4 changes: 2 additions & 2 deletions src/counters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl Counters {

let mut zipper = map.read_zipper();
while zipper.to_next_step() {
let depth = zipper.path().len();
let depth = zipper.depth();

counters.run_counter_update(depth);
if let Some(focus_node) = zipper.get_focus().try_as_tagged() {
Expand Down Expand Up @@ -187,7 +187,7 @@ impl Counters {
}
}

pub fn print_traversal<'a, V: 'a + Clone + Unpin, Z: ZipperIteration + Clone>(zipper: &Z) {
pub fn print_traversal<'a, V: 'a + Clone + Unpin, Z: ZipperIteration + ZipperPath + Clone>(zipper: &Z) {
let mut zipper = zipper.clone();

println!("{:?}", zipper.path());
Expand Down
Loading