Skip to content

Commit

Permalink
Improve documentation for KeTrees
Browse files Browse the repository at this point in the history
  • Loading branch information
p-avital committed Feb 1, 2024
1 parent 55479cf commit 95ab9c7
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 115 deletions.
8 changes: 4 additions & 4 deletions commons/zenoh-keyexpr/benches/keyexpr_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ fn main() {
let mut intersections = Averager::default();
let results = Benchmarker::benchmark(|b| {
let keys = KeySet::generate(total, wildness, no_double_stars);
let mut ketree: KeBoxTree<_> = KeBoxTree::new();
let mut vectree: KeBoxTree<_, bool, VecSetProvider> = KeBoxTree::new();
let mut hashtree: KeBoxTree<_, bool, HashMapProvider> = KeBoxTree::new();
let mut ketree = KeBoxTree::new();
let mut vectree: KeBoxTree<_, bool, VecSetProvider> = KeBoxTree::default();
let mut hashtree: KeBoxTree<_, bool, HashMapProvider> = KeBoxTree::default();
let mut ahashtree: KeBoxTree<_, bool, HashMapProvider<ahash::AHasher>> =
KeBoxTree::new();
KeBoxTree::default();
let (kearctree, mut token): (KeArcTree<i32>, _) = KeArcTree::new().unwrap();
let mut map = HashMap::new();
for key in keys.iter() {
Expand Down
11 changes: 10 additions & 1 deletion commons/zenoh-keyexpr/src/keyexpr_tree/arc_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ fn ketree_borrow_mut<'a, T, Token: TokenTrait>(
/// A shared KeTree.
///
/// The tree and its nodes have shared ownership, while their mutability is managed through the `Token`.
/// The `(node, &token)` tuple implements [`core::ops::Deref`], while `(node, &mut token)` implements [`core::ops::DerefMut`].
///
/// Most of its methods are declared in the [`ITokenKeyExprTree`] trait.
pub struct KeArcTree<
Weight,
Token: TokenTrait = DefaultToken,
Expand All @@ -82,6 +83,14 @@ impl<
> KeArcTree<Weight, DefaultToken, Wildness, Children>
{
/// Constructs the KeArcTree, returning it and its token, unless constructing the Token failed.
///
/// # Type inference papercut
/// Despite some of `KeArcTree`'s generic parameters having default values, those are only taken into
/// account by the compiler when a type is named with some parameters omitted, and not when a type is
/// infered with the same parameters unconstrained.
///
/// The simplest way to resolve this is to eventually assign to tree part of the return value
/// to a variable or field whose type is named `KeArcTree<_>` (the `Weight` parameter can generally be infered).
pub fn new() -> Result<(Self, DefaultToken), <DefaultToken as TokenTrait>::ConstructionError> {
let token = DefaultToken::new()?;
Ok((Self::with_token(&token), token))
Expand Down
21 changes: 11 additions & 10 deletions commons/zenoh-keyexpr/src/keyexpr_tree/box_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use super::impls::KeyedSetProvider;
use super::support::IterOrOption;

/// A fully owned KeTree.
///
/// Note that most of `KeBoxTree`'s methods are declared in the [`IKeyExprTree`] and [`IKeyExprTreeMut`] traits.
#[repr(C)]
pub struct KeBoxTree<
Weight,
Expand All @@ -37,17 +39,13 @@ pub struct KeBoxTree<
wildness: Wildness,
}

impl<
Weight,
Wildness: IWildness,
Children: IChildrenProvider<Box<KeyExprTreeNode<Weight, Wildness, Children>>>,
> KeBoxTree<Weight, Wildness, Children>
impl<Weight> KeBoxTree<Weight, bool, DefaultChildrenProvider>
where
DefaultChildrenProvider:
IChildrenProvider<Box<KeyExprTreeNode<Weight, bool, DefaultChildrenProvider>>>,
{
pub fn new() -> Self {
KeBoxTree {
children: Default::default(),
wildness: Wildness::non_wild(),
}
Default::default()
}
}
impl<
Expand All @@ -57,7 +55,10 @@ impl<
> Default for KeBoxTree<Weight, Wildness, Children>
{
fn default() -> Self {
Self::new()
KeBoxTree {
children: Default::default(),
wildness: Wildness::non_wild(),
}
}
}

Expand Down
45 changes: 44 additions & 1 deletion commons/zenoh-keyexpr/src/keyexpr_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,49 @@
//

//! KeTrees are specialized data structures to work with sets of values addressed by key expressions.
//!
//! Think of it like HashMaps that were specifically designed to allow iterating over key expressions related to a given query
//! in a fast and semantically correct way.
//!
//! # KeTrees
//! Key Expression Trees (KeTrees) are trees that split any KE inserted into them into its chunks.
//!
//! For example, if you take an empty KeTree, and insert the `(a/b, 0)`, `(a/b/c, 1)`, `(a/b/d, 2)`, `(a/e, 3)` and (a/@f, 4) pairs into it,
//! the tree will be as follows:
//! ```text
//! a --- e = 3
//! |- b = 0 --- c = 1
//! | |- d = 2
//! |- @f = 4
//! ```
//!
//! Note that the `a` node exists, despite no value being assigned to it. If you iterate over all nodes, the iterator may yield
//! `(a, None), (a/e, Some(3)), (a/b, Some(0)), (a/b/c, Some(1)), (a/b/d, Some(2)), (a/@f, Some(4))`.
//!
//! # Ownership
//! KeTrees come in two flavours:
//! - [`KeBoxTree`] is the easier flavour. Much like a HashMap, it uniquely owns all of its nodes and data.
//! - [`KeArcTree`] allows the shared ownership of nodes, allowing you to store subsections of the tree elsewhere
//! without worrying about lifetimes.
//!
//! # Usage
//! KeTrees were designed to maximize code reuse. As such, their core properties are reflected through the [`IKeyExprTree`] and [`IKeyExprTreeMut`] traits,
//! and the [`IKeyExprTreeExt`] and [`IKeyExprTreeExtMut`] traits provide additional convenience methods.
//!
//! # Iterators
//! KeTrees provide iterators for the following operations:
//! - Iterating on all nodes ([`IKeyExprTree::tree_iter`]/[`IKeyExprTreeMut::tree_iter_mut`])
//! - Iterating on key-value pairs in the KeTree ([`IKeyExprTreeExt::key_value_pairs`])
//! - Iterating on nodes whose KE intersects with a queried KE ([`IKeyExprTree::intersecting_nodes`], [`IKeyExprTreeMut::intersecting_nodes_mut`])
//! - Iterating on nodes whose KE are included by a queried KE ([`IKeyExprTree::included_nodes`], [`IKeyExprTreeMut::included_nodes_mut`])
//! - Iterating on nodes whose KE includes a queried KE ([`IKeyExprTree::nodes_including`], [`IKeyExprTreeMut::nodes_including_mut`])
//!
//! While the order of iteration is not guaranteed, a node will never be yielded before one of its parents if both are to appear.
//! For example, iterating on nodes that intersect with `**` in the previously defined tree is guaranteed to yield one of the following sequences:
//! - `(a, None), (a/e, Some(3)), (a/b, Some(0)), (a/b/c, Some(1)), (a/b/d, Some(2))`
//! - `(a, None), (a/e, Some(3)), (a/b, Some(0)), (a/b/d, Some(2)), (a/b/c, Some(1))`
//! - `(a, None), (a/b, Some(0)), (a/b/c, Some(1)), (a/b/d, Some(2)), (a/e, Some(3))`
//! - `(a, None), (a/b, Some(0)), (a/b/d, Some(2)), (a/b/c, Some(1)), (a/e, Some(3))`
use crate::{keyexpr, OwnedKeyExpr};
/// Allows importing all of the KeTree traits at once.
Expand All @@ -21,7 +64,7 @@ pub use traits::*;

/// An implementation of a KeTree with shared-ownership of nodes, using [`token_cell`] to allow safe access to the tree's data.
///
/// This implementation allows sharing references to members of the KeTree.
/// This implementation allows sharing ownership of members of the KeTree.
pub mod arc_tree;
pub use arc_tree::{DefaultToken, KeArcTree};
/// An implementation of a KeTree that owns all of its nodes.
Expand Down
2 changes: 1 addition & 1 deletion commons/zenoh-keyexpr/src/keyexpr_tree/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ fn test_keyset<K: Deref<Target = keyexpr> + Debug>(keys: &[K]) {
}

fn test_keyset_vec<K: Deref<Target = keyexpr>>(keys: &[K]) {
let mut tree = KeBoxTree::new();
let mut tree = KeBoxTree::default();
let mut map = HashMap::new();
for (v, k) in keys.iter().map(|k| k.deref()).enumerate() {
insert_vecset(&mut tree, &mut map, k, v);
Expand Down
Loading

0 comments on commit 95ab9c7

Please sign in to comment.