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
30 changes: 30 additions & 0 deletions pathmap-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::collections::BTreeSet;
enum PolyZipperTrait {
Zipper,
ZipperValues,
ZipperValuesAt,
ZipperReadOnlyValues,
ZipperReadOnlyConditionalValues,
ZipperReadOnlyConditionalIteration,
Expand All @@ -27,6 +28,7 @@ impl PolyZipperTrait {
match ident.to_string().as_str() {
"Zipper" => Some(Self::Zipper),
"ZipperValues" => Some(Self::ZipperValues),
"ZipperValuesAt" => Some(Self::ZipperValuesAt),
"ZipperReadOnlyValues" => Some(Self::ZipperReadOnlyValues),
"ZipperReadOnlyConditionalValues" => Some(Self::ZipperReadOnlyConditionalValues),
"ZipperReadOnlyConditionalIteration" => Some(Self::ZipperReadOnlyConditionalIteration),
Expand All @@ -49,6 +51,7 @@ fn all_poly_zipper_traits() -> BTreeSet<PolyZipperTrait> {
BTreeSet::from([
Zipper,
ZipperValues,
ZipperValuesAt,
ZipperReadOnlyValues,
ZipperReadOnlyConditionalValues,
ZipperReadOnlyConditionalIteration,
Expand Down Expand Up @@ -126,6 +129,11 @@ fn add_trait_dependencies(traits: &mut BTreeSet<PolyZipperTrait>) {
}
}
if traits.contains(&ZipperInfallibleSubtries) {
if traits.insert(ZipperValuesAt) {
changed = true;
}
}
if traits.contains(&ZipperValuesAt) {
if traits.insert(ZipperValues) {
changed = true;
}
Expand Down Expand Up @@ -320,7 +328,28 @@ fn derive_poly_zipper_with_traits(
#(#variant_arms => inner.val(),)*
}
}
}
})
} else {
None
};

// Generate ZipperValuesAt trait implementation
let zipper_values_at_impl = if traits.contains(&PolyZipperTrait::ZipperValuesAt) {
let variant_arms = &variant_arms;
let zipper_values_where = if include_where_clause {
quote! {
where
#(#inner_types: pathmap::zipper::ZipperValuesAt<V>,)*
#where_clause
}
} else {
quote! {}
};
Some(quote! {
impl #impl_generics pathmap::zipper::ZipperValuesAt<V> for #enum_name #ty_generics
#zipper_values_where
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> {
match self {
#(#variant_arms => inner.val_at(path),)*
Expand Down Expand Up @@ -874,6 +903,7 @@ fn derive_poly_zipper_with_traits(
#(#from_impls)*
#zipper_impl
#zipper_values_impl
#zipper_values_at_impl
#zipper_read_only_values_impl
#zipper_read_only_conditional_values_impl
// #zipper_forking_impl
Expand Down
21 changes: 21 additions & 0 deletions src/arena_compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ use crate::{
ZipperConcrete, ZipperReadOnlyConditionalValues, TrieRef
},
};

use crate::gxhash::{GxHasher, HashMap, HashMapExt};

/// The identifier of a node (branch node or line node)
Expand Down Expand Up @@ -2796,6 +2797,11 @@ where Storage: AsRef<[u8]>
fn val(&self) -> Option<&()> {
self.get_value().map(|_x| &())
}
}

impl<'tree, Storage> ZipperValuesAt<()> for ACTZipper<'tree, Storage, ()>
where Storage: AsRef<[u8]>
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&()> {
self.get_value_at(path.as_ref()).map(|_x| &())
}
Expand All @@ -2808,6 +2814,11 @@ where Storage: AsRef<[u8]>
//GOAT, see soundness discussion in ZipperReadOnlyValues impl below
self.get_val()
}
}

impl<'tree, Storage> ZipperValuesAt<u64> for ACTZipper<'tree, Storage, u64>
where Storage: AsRef<[u8]>
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&u64> {
//GOAT, see soundness discussion in ZipperReadOnlyValues impl below
self.get_val_at(path)
Expand Down Expand Up @@ -3328,6 +3339,16 @@ mod tests {
}
);

zipper_moving_tests::zipper_val_at_tests!(arena_compact_zipper,
|keys: &[&[u8]]| {
let btm = keys.into_iter().map(|k| (k, ())).collect::<PathMap<()>>();
ArenaCompactTree::from_zipper(btm.read_zipper(), |&_v| 0)
},
|trie: &mut ArenaCompactTree<Vec<u8>>, path: &[u8]| -> ACTZipper<'_, Vec<u8>, ()> {
trie.read_zipper_at_path(path)
}
);

zipper_iteration_tests::zipper_iteration_tests!(arena_compact_zipper,
|keys: &[&[u8]]| {
let btm = keys.into_iter().map(|k| (k, ())).collect::<PathMap<()>>();
Expand Down
9 changes: 9 additions & 0 deletions src/dependent_zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,15 @@ impl<'trie, PrimaryZ, SecondaryZ, V, C, F : Clone + for <'a> FnOnce(C, &'a [u8],
self.primary.val()
}
}
}

impl<'trie, PrimaryZ, SecondaryZ, V, C, F : Clone + for <'a> FnOnce(C, &'a [u8], usize) -> (C, Option<SecondaryZ>)> ZipperValuesAt<V>
for DependentProductZipperG<'trie, PrimaryZ, SecondaryZ, V, C, F>
where
V: Clone + Send + Sync,
PrimaryZ: ZipperMoving + ZipperPath + ZipperValuesAt<V>,
SecondaryZ: ZipperMoving + ZipperPath + ZipperValuesAt<V>,
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> {
if let Some(idx) = self.factor_idx(true) {
self.secondary[idx].val_at(path)
Expand Down
3 changes: 3 additions & 0 deletions src/empty_zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ impl ZipperIteration for EmptyZipper {

impl<V> ZipperValues<V> for EmptyZipper {
fn val(&self) -> Option<&V> { None }
}

impl<V> ZipperValuesAt<V> for EmptyZipper {
fn val_at<K: AsRef<[u8]>>(&self, _path: K) -> Option<&V> { None }
}

Expand Down
2 changes: 1 addition & 1 deletion src/experimental/zipper_algebra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2854,7 +2854,7 @@ mod zipper_algebra_poly {
use pathmap_derive::PolyZipperExplicit;

#[derive(PolyZipperExplicit)]
#[poly_zipper_explicit(traits(ZipperMoving, ZipperValues, ZipperConcrete))]
#[poly_zipper_explicit(traits(ZipperMoving, ZipperValues, ZipperValuesAt, ZipperConcrete))]
pub(super) enum SomeMutRefZ<'a, 'trie, 'path, V: Clone + Send + Sync + Unpin, A: Allocator> {
RZ(&'a mut ReadZipperUntracked<'trie, 'path, V, A>),
RZT(&'a mut ReadZipperTracked<'trie, 'path, V, A>),
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ mod empty_zipper;
mod prefix_zipper;
mod overlay_zipper;
mod dependent_zipper;
mod subtract_zipper;
mod path_tracker;
mod trie_ref;
mod dense_byte_node;
Expand Down
28 changes: 27 additions & 1 deletion src/overlay_zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use arrayvec::ArrayVec;
use fast_slice_utils::find_prefix_overlap;
use crate::utils::{BitMask, ByteMask};
use crate::zipper::{Zipper, ZipperMoving, ZipperPath, PathObserver, ZipperIteration, ZipperValues};
use crate::zipper::{Zipper, ZipperMoving, ZipperPath, PathObserver, ZipperIteration, ZipperValues, ZipperValuesAt};

/// Zipper that traverses a virtual trie formed by fusing the tries of two other zippers
pub struct OverlayZipper<AV, BV, OutV, AZipper, BZipper, Mapping>
Expand Down Expand Up @@ -102,6 +102,15 @@ impl<AV, BV, OutV, AZipper, BZipper, Mapping> ZipperValues<OutV>
fn val(&self) -> Option<&OutV> {
(self.mapping)(self.a.val(), self.b.val())
}
}

impl<AV, BV, OutV, AZipper, BZipper, Mapping> ZipperValuesAt<OutV>
for OverlayZipper<AV, BV, OutV, AZipper, BZipper, Mapping>
where
AZipper: ZipperValuesAt<AV>,
BZipper: ZipperValuesAt<BV>,
Mapping: for<'a> Fn(Option<&'a AV>, Option<&'a BV>) -> Option<&'a OutV>,
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&OutV> {
(self.mapping)(self.a.val_at(&path), self.b.val_at(&path))
}
Expand Down Expand Up @@ -441,6 +450,23 @@ mod tests {
}
);

zipper_moving_tests::zipper_val_at_tests!(overlay_zipper,
|keys: &[&[u8]]| {
let cutoff = keys.len() / 3 * 2;
// eprintln!("keys={:?}", &keys);
eprintln!("a_keys={:?}\nb_keys={:?}", &keys[..cutoff], &keys[cutoff..]);
let a = keys[..cutoff].into_iter().map(|k| (k, ())).collect::<PathMap<()>>();
let b = keys[cutoff..].into_iter().map(|k| (k, ())).collect::<PathMap<()>>();
(a, b)
},
|trie: &mut (PathMap<()>, PathMap<()>), path: &[u8]| -> OZ<'_, ()> {
OverlayZipper::new(
trie.0.read_zipper_at_path(path),
trie.1.read_zipper_at_path(path),
)
}
);

zipper_iteration_tests::zipper_iteration_tests!(overlay_zipper,
|keys: &[&[u8]]| {
let cutoff = keys.len() / 3 * 2;
Expand Down
7 changes: 4 additions & 3 deletions src/path_tracker.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use crate::{
utils::ByteMask,
zipper::{
PathObserver, Zipper, ZipperAbsolutePath, ZipperMoving, ZipperIteration,
ZipperPath, ZipperPathBuffer, ZipperValues,
ZipperReadOnlyValues, ZipperReadOnlyConditionalValues,
PathObserver, Zipper, ZipperAbsolutePath, ZipperIteration, ZipperMoving, ZipperPath, ZipperPathBuffer, ZipperReadOnlyConditionalValues, ZipperReadOnlyValues, ZipperValues, ZipperValuesAt
},
};

Expand Down Expand Up @@ -185,6 +183,9 @@ impl<Z: ZipperMoving> ZipperAbsolutePath for PathTracker<Z> {

impl<Z: ZipperValues<V>, V> ZipperValues<V> for PathTracker<Z> {
fn val(&self) -> Option<&V> { self.zipper.val() }
}

impl<Z: ZipperValuesAt<V>, V> ZipperValuesAt<V> for PathTracker<Z> {
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> { self.zipper.val_at(path) }
}

Expand Down
31 changes: 30 additions & 1 deletion src/poly_zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,15 @@ mod tests {
}
);

crate::zipper::zipper_moving_tests::zipper_val_at_tests!(poly_zipper_pm,
|keys: &[&[u8]]| {
keys.iter().map(|k| (k, ())).collect::<PathMap<()>>()
},
|btm: &mut PathMap<()>, path: &[u8]| -> _ {
TestPolyZipper::PathMapU(btm.read_zipper_at_path(path))
}
);

crate::zipper::zipper_iteration_tests::zipper_iteration_tests!(poly_zipper_pm,
|keys: &[&[u8]]| {
keys.iter().map(|k| (k, ())).collect::<PathMap<()>>()
Expand All @@ -129,6 +138,17 @@ mod tests {
}
);

#[cfg(feature = "arena_compact")]
crate::zipper::zipper_moving_tests::zipper_val_at_tests!(poly_zipper_act,
|keys: &[&[u8]]| {
let btm = keys.iter().map(|k| (k, ())).collect::<PathMap<()>>();
ACTVec::from_zipper(btm.read_zipper(), |()| 0)
},
|act: &mut ACTVec, path: &[u8]| -> _ {
TestPolyZipper::ACTVecPrefix(PrefixZipper::new(&[], act.read_zipper_at_path(path)))
}
);

#[cfg(feature = "arena_compact")]
crate::zipper::zipper_iteration_tests::zipper_iteration_tests!(poly_zipper_act,
|keys: &[&[u8]]| {
Expand All @@ -143,7 +163,7 @@ mod tests {
// ======================================================================================
// Cocktail of recursive zipper madness
#[derive(PolyZipperExplicit)]
#[poly_zipper_explicit(traits(Zipper, ZipperValues, ZipperMoving, ZipperPath, ZipperIteration))]
#[poly_zipper_explicit(traits(Zipper, ZipperValues, ZipperValuesAt, ZipperMoving, ZipperPath, ZipperIteration))]
pub enum ExprFactor<'trie, V: Clone + Send + Sync + Unpin + 'static = ()> {
Specific(ReadZipperOwned<V>),
Generic(PrefixZipper<'trie,
Expand All @@ -164,4 +184,13 @@ mod tests {
ExprFactor::Specific(btm.clone().into_read_zipper(path))
}
);

crate::zipper::zipper_moving_tests::zipper_val_at_tests!(recursive_zipper_madness,
|keys: &[&[u8]]| {
keys.iter().map(|k| (k, ())).collect::<PathMap<()>>()
},
|btm: &mut PathMap<()>, path: &[u8]| -> _ {
ExprFactor::Specific(btm.clone().into_read_zipper(path))
}
);
}
7 changes: 7 additions & 0 deletions src/prefix_zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ impl<'prefix, Z, V> ZipperValues<V> for PrefixZipper<'prefix, Z>
}
self.source.val()
}
}

impl<'prefix, Z, V> ZipperValuesAt<V> for PrefixZipper<'prefix, Z>
where
Z: ZipperValuesAt<V>
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> {
let path = self.adjust_lookup_path(path.as_ref())?;
self.source.val_at(path)
Expand Down Expand Up @@ -759,6 +765,7 @@ mod tests {
use crate::zipper::ZipperPath;
use crate::zipper::ZipperReadOnlyValues;
use crate::zipper::ZipperValues;
use crate::zipper::ZipperValuesAt;

//The whole prefix is the root prefix, so these run the shared suites against a `PrefixZipper`
//whose focus begins in the source
Expand Down
33 changes: 33 additions & 0 deletions src/product_zipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ impl<'trie, V: Clone + Send + Sync + Unpin + 'trie, A: Allocator + 'trie> Zipper
fn val(&self) -> Option<&V> {
unsafe{ self.z.get_val() }
}
}

impl<'trie, V: Clone + Send + Sync + Unpin + 'trie, A: Allocator + 'trie> ZipperValuesAt<V> for ProductZipper<'_, 'trie, V, A> {
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> {
unsafe{ self.z.get_val_at(path) }
}
Expand Down Expand Up @@ -571,6 +574,15 @@ impl<'trie, PrimaryZ, SecondaryZ, V> ZipperValues<V>
self.primary.val()
}
}
}

impl<'trie, PrimaryZ, SecondaryZ, V> ZipperValuesAt<V>
for ProductZipperG<'trie, PrimaryZ, SecondaryZ, V>
where
V: Clone + Send + Sync,
PrimaryZ: ZipperMoving + ZipperPath + ZipperValuesAt<V>,
SecondaryZ: ZipperMoving + ZipperPath + ZipperValuesAt<V>,
{
fn val_at<K: AsRef<[u8]>>(&self, path: K) -> Option<&V> {
if let Some(idx) = self.factor_idx(true) {
self.secondary[idx].val_at(path)
Expand Down Expand Up @@ -907,6 +919,7 @@ impl <Z : ZipperMoving> ZipperMoving for OneFactor<Z> { zipper_impl_lens!(Zipper
impl <Z : ZipperMoving + ZipperPath> ZipperPath for OneFactor<Z> { zipper_impl_lens!(ZipperPath self => self.z); }
impl <Z : ZipperIteration> ZipperIteration for OneFactor<Z> { zipper_impl_lens!(ZipperIteration self => self.z); }
impl <V, Z : ZipperValues<V>> ZipperValues<V> for OneFactor<Z> { zipper_impl_lens!(ZipperValues self => self.z); }
impl <V, Z : ZipperValuesAt<V>> ZipperValuesAt<V> for OneFactor<Z> { zipper_impl_lens!(ZipperValuesAt self => self.z); }
impl <V, Z : ZipperForking<V>> ZipperForking<V> for OneFactor<Z> { type ReadZipperT<'a> = Z::ReadZipperT<'a> where Z: 'a; zipper_impl_lens!(ZipperForking self => self.z); }
impl <V: Clone + Send + Sync, A: Allocator, Z : ZipperSubtries<V, A>> ZipperSubtries<V, A> for OneFactor<Z> { zipper_impl_lens!(ZipperSubtries self => self.z); }
impl <V: Clone + Send + Sync, A: Allocator, Z : ZipperInfallibleSubtries<V, A>> ZipperInfallibleSubtries<V, A> for OneFactor<Z> { zipper_impl_lens!(ZipperInfallibleSubtries self => self.z); }
Expand Down Expand Up @@ -1913,6 +1926,16 @@ mod tests {
ProductZipper::new::<_, TrieRef<()>, _>(btm.read_zipper_at_path(path), [])
});

crate::zipper::zipper_moving_tests::zipper_val_at_tests!(product_zipper,
|keys: &[&[u8]]| {
let mut btm = PathMap::new();
keys.iter().for_each(|k| { btm.set_val_at(k, ()); });
btm
},
|btm: &mut PathMap<()>, path: &[u8]| -> _ {
ProductZipper::new::<_, TrieRef<()>, _>(btm.read_zipper_at_path(path), [])
});

crate::zipper::zipper_iteration_tests::zipper_iteration_tests!(product_zipper,
|keys: &[&[u8]]| {
let mut btm = PathMap::new();
Expand All @@ -1933,6 +1956,16 @@ mod tests {
ProductZipperG::new::<[ReadZipperUntracked<()>; 0]>(btm.read_zipper_at_path(path), [])
});

crate::zipper::zipper_moving_tests::zipper_val_at_tests!(product_zipper_generic,
|keys: &[&[u8]]| {
let mut btm = PathMap::new();
keys.iter().for_each(|k| { btm.set_val_at(k, ()); });
btm
},
|btm: &mut PathMap<()>, path: &[u8]| -> _ {
ProductZipperG::new::<[ReadZipperUntracked<()>; 0]>(btm.read_zipper_at_path(path), [])
});

crate::zipper::zipper_iteration_tests::zipper_iteration_tests!(product_zipper_generic,
|keys: &[&[u8]]| {
let mut btm = PathMap::new();
Expand Down
Loading