Skip to content
This repository has been archived by the owner on May 11, 2023. It is now read-only.

Feat: Add PositionPath and PositionPathIter to calculate the path and side positions from root to leaf #55

Merged
merged 10 commits into from
Jan 10, 2022
3 changes: 3 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod msb;
mod node;
mod path_iterator;
mod position;
mod position_path;
mod storage_map;
mod subtree;

Expand All @@ -14,6 +15,8 @@ pub use position::Position;
pub use storage_map::{StorageError, StorageMap};
pub use subtree::Subtree;

pub(crate) use position_path::PositionPath;

pub const NODE: u8 = 0x01;
pub const LEAF: u8 = 0x00;

Expand Down
4 changes: 1 addition & 3 deletions src/common/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ pub trait Node {
fn key_size_in_bits() -> usize {
size_of::<Self::Key>() * 8
}
fn max_height() -> usize {
Self::key_size_in_bits()
}

fn height(&self) -> u32;
fn leaf_key(&self) -> Self::Key;
fn is_leaf(&self) -> bool;
}
Expand Down
26 changes: 13 additions & 13 deletions src/common/path_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ where
// 0 7 00 02 04 06 08 10 12 14 252 254
// 00 01 02 03 04 05 06 07 126 127
//
let initial_offset = T::key_size_in_bits() - T::max_height();
let initial_offset = T::key_size_in_bits() - root.height() as usize;
Self {
leaf: leaf.clone(),
current: Some(initial),
Expand Down Expand Up @@ -180,11 +180,11 @@ mod test {
use crate::common::{AsPathIterator, Bytes8, Node, ParentNode};

#[derive(Debug, Clone, PartialEq)]
struct TestNode<const LEAF_BITS: usize> {
struct TestNode {
value: u64,
}

impl<const LEAF_BITS: usize> TestNode<LEAF_BITS> {
impl TestNode {
pub fn in_order_index(&self) -> u64 {
self.value
}
Expand Down Expand Up @@ -217,11 +217,11 @@ mod test {
}
}

impl<const LEAF_BITS: usize> Node for TestNode<LEAF_BITS> {
impl Node for TestNode {
type Key = Bytes8;

fn max_height() -> usize {
LEAF_BITS
fn height(&self) -> u32 {
TestNode::height(self)
}

fn leaf_key(&self) -> Self::Key {
Expand All @@ -233,7 +233,7 @@ mod test {
}
}

impl<const LEAF_BITS: usize> ParentNode for TestNode<LEAF_BITS> {
impl ParentNode for TestNode {
fn left_child(&self) -> Self {
TestNode::child(self, -1)
}
Expand Down Expand Up @@ -261,7 +261,7 @@ mod test {
// 00 02 04 06 08 10 12 14
// 00 01 02 03 04 05 06 07
//
type Node = TestNode<3>;
type Node = TestNode;
let root = Node::from_in_order_index(7);

{
Expand Down Expand Up @@ -387,7 +387,7 @@ mod test {
// 00 02 04 06 08 10 12 14
// 00 01 02 03 04 05 06 07
//
type Node = TestNode<3>;
type Node = TestNode;
let root = Node::from_in_order_index(7); // 2^3 - 1

{
Expand Down Expand Up @@ -497,7 +497,7 @@ mod test {

#[test]
fn test_path_iter_height_4() {
type Node = TestNode<4>;
type Node = TestNode;
let root = Node::from_in_order_index(15); // 2^4 - 1
let leaf = Node::from_leaf_index(4); // 0b0100

Expand All @@ -516,7 +516,7 @@ mod test {

#[test]
fn test_path_iter_height_8() {
type Node = TestNode<8>;
type Node = TestNode;
let root = Node::from_in_order_index(255); // 2^8 - 1
let leaf = Node::from_leaf_index(61); // 0b00111101

Expand All @@ -539,7 +539,7 @@ mod test {

#[test]
fn test_path_iter_returns_root_root_when_root_is_leaf() {
type Node = TestNode<1>;
type Node = TestNode;
let root = Node::from_in_order_index(0);
let leaf = Node::from_leaf_index(0);

Expand All @@ -552,7 +552,7 @@ mod test {

#[test]
fn test_path_iter_into_path_nodes_and_side_nodes() {
type Node = TestNode<3>;
type Node = TestNode;
let root = Node::from_in_order_index(7);
let leaf = Node::from_leaf_index(0);
let iter = root.as_path_iter(&leaf);
Expand Down
41 changes: 41 additions & 0 deletions src/common/position.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::common::{Bytes8, PositionPath};

/// #Position
///
/// A `Position` represents a node's position in a binary tree by encapsulating the node's index
Expand Down Expand Up @@ -80,6 +82,11 @@ impl Position {
self.0
}

pub fn leaf_index(self) -> u64 {
assert!(self.is_leaf());
self.in_order_index() / 2
}

/// Construct a position from an in-order index.
pub fn from_in_order_index(index: u64) -> Self {
Position(index)
Expand Down Expand Up @@ -168,6 +175,14 @@ impl Position {
!self.is_leaf()
}

/// Given a leaf position and the total count of leaves in a tree, get the path from this
/// position to the given leaf position. The shape of the tree is defined by the `leaves_count`
/// parameter and constrains the path.
/// See [PositionPath](crate::common::PositionPath).
pub fn path(self, leaf: &Self, leaves_count: u64) -> PositionPath {
PositionPath::new(self, *leaf, leaves_count)
}

// PRIVATE

/// The child position of the current position given by the direction.
Expand Down Expand Up @@ -218,6 +233,32 @@ impl Position {
}
}

impl crate::common::Node for Position {
type Key = Bytes8;

fn height(&self) -> u32 {
Position::height(*self)
}

fn leaf_key(&self) -> Self::Key {
Position::leaf_index(*self).to_be_bytes()
}

fn is_leaf(&self) -> bool {
Position::is_leaf(*self)
}
}

impl crate::common::ParentNode for Position {
fn left_child(&self) -> Self {
Position::left_child(*self)
}

fn right_child(&self) -> Self {
Position::right_child(*self)
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
Loading