Skip to content

Commit

Permalink
wip: history independant treap
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuhvi committed Dec 15, 2023
1 parent 9596efc commit e45cacd
Showing 1 changed file with 230 additions and 16 deletions.
246 changes: 230 additions & 16 deletions mast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,232 @@
#![allow(unused)]

mod node;
mod storage;
mod tree;

use crate::node::Node;

// // TODO: maybe add nonce for encrypted trees.
// // TODO: why add header in each node? or in the Mast commit?
// // Would we need to read a node without traversing down from the Mast commit?
// pub struct Mast {
// /// The name of this Mast to be used as a prefix for all nodes
// /// in the storage, seperating different Masts.
// name: String,
// root: Option<Hash>,
// storage: MastStorage,
// }
use blake3::{Hash, Hasher};

use std::cmp::Ordering;
use std::mem;

type Key = Box<[u8]>;
type Value = Box<[u8]>;

const KEY: [u8; 32] = [1_u8; 32];

#[derive(Debug, Clone)]
pub struct Node {
key: Key,
value: Value,

priority: Hash,

left: Option<Box<Node>>,
right: Option<Box<Node>>,
}

enum RemovalCases {
RemoveNode,
RotateLeft,
RotateRight,
}

impl Node {
pub fn new(key: &[u8], value: &[u8]) -> Node {
let priority = Hasher::new().update(&key).finalize();

Node {
key: key.into(),
value: value.into(),
priority,
left: None,
right: None,
}
}

pub fn get(&self, key: &[u8]) -> Option<&[u8]> {
match key.cmp(&self.key) {
Ordering::Equal => Some(&self.value),
Ordering::Less => self.left.as_ref().and_then(|n| n.get(key)),
Ordering::Greater => self.right.as_ref().and_then(|n| n.get(key)),
}
}

// pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
// match key.cmp(&self.key) {
// Ordering::Equal => Some(&mut self.value),
// Ordering::Less => self.left.as_mut().and_then(|n| n.get_mut(key)),
// Ordering::Greater => self.right.as_mut().and_then(|n| n.get_mut(key)),
// }
// }

pub fn insert_or_replace(subtree: &mut Option<Box<Node>>, new: Node) -> Option<Value> {
match *subtree {
None => {
mem::replace(subtree, Some(Box::new(new)));
None
}
Some(ref mut node) => node.insert(new),
}
}

pub fn insert(&mut self, node: Node) -> Option<Value> {
match node.key.cmp(&self.key) {
Ordering::Equal => {
if self.priority.as_bytes() < node.priority.as_bytes() {
self.priority = node.priority;
}
Some(mem::replace(&mut self.value, node.value))
}
Ordering::Less => {
let old_value = Node::insert_or_replace(&mut self.left, node);
if self.is_heap_property_violated(&self.left) {
self.right_rotate();
}
old_value
}
Ordering::Greater => {
let old_value = Node::insert_or_replace(&mut self.right, node);
if self.is_heap_property_violated(&self.right) {
self.left_rotate();
}
old_value
}
}
}

// pub fn remove(subtree: &mut Option<Box<Node<K, V>>>, key: &K) -> Option<V> {
// {
// let node = match *subtree {
// None => return None,
// Some(ref mut n) => n,
// };
// match key.cmp(&node.key) {
// Ordering::Less => return Node::remove(&mut node.left, key),
// Ordering::Greater => return Node::remove(&mut node.right, key),
// Ordering::Equal => {}
// }
// }
// Node::rotate_down(subtree)
// }
//
// fn rotate_down(subtree: &mut Option<Box<Node<K, V>>>) -> Option<V> {
// let case = match *subtree {
// None => return None,
// Some(ref root) => match (&root.left, &root.right) {
// (&None, &None) => RemovalCases::RemoveNode,
// (&Some(ref left), &Some(ref right)) => {
// if left.priority >= right.priority {
// RemovalCases::RotateRight
// } else {
// RemovalCases::RotateLeft
// }
// }
// (&Some(_), &None) => RemovalCases::RotateRight,
// (&None, &Some(_)) => RemovalCases::RotateLeft,
// },
// };
// match case {
// RemovalCases::RemoveNode => subtree.take().map(|n| n.value),
// RemovalCases::RotateLeft => subtree.as_mut().and_then(|n| {
// n.left_rotate();
// Node::rotate_down(&mut n.left)
// }),
// RemovalCases::RotateRight => subtree.as_mut().and_then(|n| {
// n.right_rotate();
// Node::rotate_down(&mut n.right)
// }),
// }
// }

// #[inline]
fn is_heap_property_violated(&self, subtree: &Option<Box<Node>>) -> bool {
match *subtree {
None => false,
Some(ref b) => self.priority.as_bytes() < b.priority.as_bytes(),
}
}

// q p
// / \ / \
// p C ---> A q
// / \ / \
// A B B C
fn right_rotate(&mut self) {
// Cut left subtree of q
let left = mem::replace(&mut self.left, None);
if let Some(mut node) = left {
// Let subtree p be root and `node` point to q
mem::swap(self, &mut *node);
// Move subtree B from p to left subtree of q
mem::swap(&mut self.right, &mut node.left);
// Let q be right child of p
mem::replace(&mut self.right, Some(node));
}
}

// p q
// / \ / \
// A q ---> p C
// / \ / \
// B C A B
fn left_rotate(&mut self) {
// Cut right subtree of p
let right = mem::replace(&mut self.right, None);
if let Some(mut node) = right {
// Let subtree q be root and `node` point to p
mem::swap(self, &mut *node);
// Move subtree B from q to right subtree of p
mem::swap(&mut self.left, &mut node.right);
// Let p be left child of q
mem::replace(&mut self.left, Some(node));
}
}

pub fn as_mermaid_graph(&self) -> String {
let mut graph = String::from("graph TD;\n"); // Start of the Mermaid graph
build_graph_string(&Some(self.clone().into()), &mut graph);
graph
}
}

fn build_graph_string(node: &Option<Box<Node>>, graph: &mut String) {
if let Some(ref n) = node {
let key = bytes_to_string(&n.key);
let node_label = format!("{}({}:)", key, key);

graph.push_str(&format!(" {};\n", node_label));

if n.left.is_some() {
let key = bytes_to_string(&n.left.as_ref().unwrap().key);
let left_label = format!("{}({})", key, key);

graph.push_str(&format!(" {} --> {};\n", node_label, left_label));
build_graph_string(&n.left, graph);
}

if n.right.is_some() {
let key = bytes_to_string(&n.right.as_ref().unwrap().key);
let right_label = format!("{}({})", key, key);

graph.push_str(&format!(" {} --> {};\n", node_label, right_label));
build_graph_string(&n.right, graph);
}
}
}

fn bytes_to_string(bytes: &[u8]) -> String {
bytes.iter().map(|&b| b.to_string()).collect()
}

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

#[test]
fn basic() {
let mut tree = Node::new(b"a", b"0");

for i in 0..254 {
tree.insert(Node::new(&[i], b"0"));
}

println!("{}", tree.as_mermaid_graph())
}
}

0 comments on commit e45cacd

Please sign in to comment.