From e45cacd61a6cd005a270f8dbc1e716e086a84995 Mon Sep 17 00:00:00 2001 From: nazeh Date: Fri, 15 Dec 2023 23:09:12 +0300 Subject: [PATCH] wip: history independant treap --- mast/src/lib.rs | 242 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 228 insertions(+), 14 deletions(-) diff --git a/mast/src/lib.rs b/mast/src/lib.rs index efcb3f0..41cb69d 100644 --- a/mast/src/lib.rs +++ b/mast/src/lib.rs @@ -1,18 +1,232 @@ #![allow(unused)] -mod node; -mod storage; -mod tree; +use blake3::{Hash, Hasher}; -use crate::node::Node; +use std::cmp::Ordering; +use std::mem; -// // 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, -// storage: MastStorage, -// } +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>, + right: Option>, +} + +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>, new: Node) -> Option { + 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 { + 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>>, key: &K) -> Option { + // { + // 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>>) -> Option { + // 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>) -> 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>, 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()) + } +}