From 2d44a9a9566a80d64d0926a13a0a813b8fc953f6 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 10 Sep 2022 08:58:08 +0800 Subject: [PATCH] refactor: rename docuemnt tree to node tree --- .../lib-ot/src/core/document/document.rs | 54 +++++++++---------- .../src/core/document/document_operation.rs | 52 +++++++++--------- shared-lib/lib-ot/src/core/document/node.rs | 28 +++++++--- .../lib-ot/src/core/document/transaction.rs | 38 ++++++------- shared-lib/lib-ot/tests/node/script.rs | 8 +-- 5 files changed, 96 insertions(+), 84 deletions(-) diff --git a/shared-lib/lib-ot/src/core/document/document.rs b/shared-lib/lib-ot/src/core/document/document.rs index 70c19030cb..5c362c5fac 100644 --- a/shared-lib/lib-ot/src/core/document/document.rs +++ b/shared-lib/lib-ot/src/core/document/document.rs @@ -1,40 +1,39 @@ use crate::core::document::position::Path; -use crate::core::{DocumentOperation, Node, NodeAttributes, NodeData, OperationTransform, TextDelta, Transaction}; +use crate::core::{Node, NodeAttributes, NodeData, NodeOperation, OperationTransform, TextDelta, Transaction}; use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; use indextree::{Arena, Children, FollowingSiblings, NodeId}; -pub struct DocumentTree { +pub struct NodeTree { arena: Arena, root: NodeId, } -impl Default for DocumentTree { +impl Default for NodeTree { fn default() -> Self { Self::new() } } -impl DocumentTree { - pub fn new() -> DocumentTree { +impl NodeTree { + pub fn new() -> NodeTree { let mut arena = Arena::new(); - let root = arena.new_node(NodeData::new("root")); - DocumentTree { arena, root } + NodeTree { arena, root } } /// /// # Examples /// /// ``` - /// use lib_ot::core::{DocumentOperation, DocumentTree, Node, Path}; + /// use lib_ot::core::{NodeOperation, NodeTree, Node, Path}; /// let nodes = vec![Node::new("text")]; /// let root_path: Path = vec![0].into(); - /// let op = DocumentOperation::Insert {path: root_path.clone(),nodes }; + /// let op = NodeOperation::Insert {path: root_path.clone(),nodes }; /// - /// let mut document = DocumentTree::new(); - /// document.apply_op(&op).unwrap(); - /// let node_id = document.node_at_path(&root_path).unwrap(); - /// let node_path = document.path_of_node(node_id); + /// let mut node_tree = NodeTree::new(); + /// node_tree.apply_op(&op).unwrap(); + /// let node_id = node_tree.node_at_path(&root_path).unwrap(); + /// let node_path = node_tree.path_of_node(node_id); /// debug_assert_eq!(node_path, root_path); /// ``` pub fn node_at_path>(&self, path: T) -> Option { @@ -51,9 +50,10 @@ impl DocumentTree { } pub fn path_of_node(&self, node_id: NodeId) -> Path { - let mut path: Vec = Vec::new(); - let mut ancestors = node_id.ancestors(&self.arena).skip(1); + let mut path = vec![]; let mut current_node = node_id; + // Use .skip(1) on the ancestors iterator to skip the root node. + let mut ancestors = node_id.ancestors(&self.arena).skip(1); let mut parent = ancestors.next(); while parent.is_some() { @@ -94,15 +94,15 @@ impl DocumentTree { /// # Examples /// /// ``` - /// use lib_ot::core::{DocumentOperation, DocumentTree, Node, Path}; + /// use lib_ot::core::{NodeOperation, NodeTree, Node, Path}; /// let node = Node::new("text"); /// let inserted_path: Path = vec![0].into(); /// - /// let mut document = DocumentTree::new(); - /// document.apply_op(&DocumentOperation::Insert {path: inserted_path.clone(),nodes: vec![node.clone()] }).unwrap(); + /// let mut node_tree = NodeTree::new(); + /// node_tree.apply_op(&NodeOperation::Insert {path: inserted_path.clone(),nodes: vec![node.clone()] }).unwrap(); /// - /// let inserted_note = document.node_at_path(&inserted_path).unwrap(); - /// let inserted_data = document.get_node_data(inserted_note).unwrap(); + /// let inserted_note = node_tree.node_at_path(&inserted_path).unwrap(); + /// let inserted_data = node_tree.get_node_data(inserted_note).unwrap(); /// assert_eq!(inserted_data.node_type, node.note_type); /// ``` pub fn child_from_node_with_index(&self, at_node: NodeId, index: usize) -> Option { @@ -149,12 +149,12 @@ impl DocumentTree { Ok(()) } - pub fn apply_op(&mut self, op: &DocumentOperation) -> Result<(), OTError> { + pub fn apply_op(&mut self, op: &NodeOperation) -> Result<(), OTError> { match op { - DocumentOperation::Insert { path, nodes } => self.apply_insert(path, nodes), - DocumentOperation::Update { path, attributes, .. } => self.apply_update(path, attributes), - DocumentOperation::Delete { path, nodes } => self.apply_delete(path, nodes.len()), - DocumentOperation::TextEdit { path, delta, .. } => self.apply_text_edit(path, delta), + NodeOperation::Insert { path, nodes } => self.apply_insert(path, nodes), + NodeOperation::Update { path, attributes, .. } => self.apply_update(path, attributes), + NodeOperation::Delete { path, nodes } => self.apply_delete(path, nodes.len()), + NodeOperation::TextEdit { path, delta, .. } => self.apply_text_edit(path, delta), } } @@ -195,7 +195,7 @@ impl DocumentTree { // recursive append the subtrees to the node fn append_subtree(&mut self, parent: &NodeId, insert_children: &[Node]) { for child in insert_children { - let child_id = self.arena.new_node(child.to_node_data()); + let child_id = self.arena.new_node(child.into()); parent.append(child_id, &mut self.arena); self.append_subtree(&child_id, &child.children); @@ -204,7 +204,7 @@ impl DocumentTree { fn insert_subtree_before(&mut self, before: &NodeId, insert_children: &[Node]) { for child in insert_children { - let child_id = self.arena.new_node(child.to_node_data()); + let child_id = self.arena.new_node(child.into()); before.insert_before(child_id, &mut self.arena); self.append_subtree(&child_id, &child.children); diff --git a/shared-lib/lib-ot/src/core/document/document_operation.rs b/shared-lib/lib-ot/src/core/document/document_operation.rs index c162f39afe..61d4a63ccd 100644 --- a/shared-lib/lib-ot/src/core/document/document_operation.rs +++ b/shared-lib/lib-ot/src/core/document/document_operation.rs @@ -3,7 +3,7 @@ use crate::core::{Node, NodeAttributes, TextDelta}; #[derive(Clone, serde::Serialize, serde::Deserialize)] #[serde(tag = "op")] -pub enum DocumentOperation { +pub enum NodeOperation { #[serde(rename = "insert")] Insert { path: Path, nodes: Vec }, #[serde(rename = "update")] @@ -23,74 +23,74 @@ pub enum DocumentOperation { }, } -impl DocumentOperation { +impl NodeOperation { pub fn path(&self) -> &Path { match self { - DocumentOperation::Insert { path, .. } => path, - DocumentOperation::Update { path, .. } => path, - DocumentOperation::Delete { path, .. } => path, - DocumentOperation::TextEdit { path, .. } => path, + NodeOperation::Insert { path, .. } => path, + NodeOperation::Update { path, .. } => path, + NodeOperation::Delete { path, .. } => path, + NodeOperation::TextEdit { path, .. } => path, } } - pub fn invert(&self) -> DocumentOperation { + pub fn invert(&self) -> NodeOperation { match self { - DocumentOperation::Insert { path, nodes } => DocumentOperation::Delete { + NodeOperation::Insert { path, nodes } => NodeOperation::Delete { path: path.clone(), nodes: nodes.clone(), }, - DocumentOperation::Update { + NodeOperation::Update { path, attributes, old_attributes, - } => DocumentOperation::Update { + } => NodeOperation::Update { path: path.clone(), attributes: old_attributes.clone(), old_attributes: attributes.clone(), }, - DocumentOperation::Delete { path, nodes } => DocumentOperation::Insert { + NodeOperation::Delete { path, nodes } => NodeOperation::Insert { path: path.clone(), nodes: nodes.clone(), }, - DocumentOperation::TextEdit { path, delta, inverted } => DocumentOperation::TextEdit { + NodeOperation::TextEdit { path, delta, inverted } => NodeOperation::TextEdit { path: path.clone(), delta: inverted.clone(), inverted: delta.clone(), }, } } - pub fn clone_with_new_path(&self, path: Path) -> DocumentOperation { + pub fn clone_with_new_path(&self, path: Path) -> NodeOperation { match self { - DocumentOperation::Insert { nodes, .. } => DocumentOperation::Insert { + NodeOperation::Insert { nodes, .. } => NodeOperation::Insert { path, nodes: nodes.clone(), }, - DocumentOperation::Update { + NodeOperation::Update { attributes, old_attributes, .. - } => DocumentOperation::Update { + } => NodeOperation::Update { path, attributes: attributes.clone(), old_attributes: old_attributes.clone(), }, - DocumentOperation::Delete { nodes, .. } => DocumentOperation::Delete { + NodeOperation::Delete { nodes, .. } => NodeOperation::Delete { path, nodes: nodes.clone(), }, - DocumentOperation::TextEdit { delta, inverted, .. } => DocumentOperation::TextEdit { + NodeOperation::TextEdit { delta, inverted, .. } => NodeOperation::TextEdit { path, delta: delta.clone(), inverted: inverted.clone(), }, } } - pub fn transform(a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation { + pub fn transform(a: &NodeOperation, b: &NodeOperation) -> NodeOperation { match a { - DocumentOperation::Insert { path: a_path, nodes } => { + NodeOperation::Insert { path: a_path, nodes } => { let new_path = Path::transform(a_path, b.path(), nodes.len() as i64); b.clone_with_new_path(new_path) } - DocumentOperation::Delete { path: a_path, nodes } => { + NodeOperation::Delete { path: a_path, nodes } => { let new_path = Path::transform(a_path, b.path(), nodes.len() as i64); b.clone_with_new_path(new_path) } @@ -101,7 +101,7 @@ impl DocumentOperation { #[cfg(test)] mod tests { - use crate::core::{Delta, DocumentOperation, Node, NodeAttributes, Path}; + use crate::core::{Delta, Node, NodeAttributes, NodeOperation, Path}; #[test] fn test_transform_path_1() { @@ -153,7 +153,7 @@ mod tests { #[test] fn test_serialize_insert_operation() { - let insert = DocumentOperation::Insert { + let insert = NodeOperation::Insert { path: Path(vec![0, 1]), nodes: vec![Node::new("text")], }; @@ -166,7 +166,7 @@ mod tests { #[test] fn test_serialize_insert_sub_trees() { - let insert = DocumentOperation::Insert { + let insert = NodeOperation::Insert { path: Path(vec![0, 1]), nodes: vec![Node { note_type: "text".into(), @@ -184,7 +184,7 @@ mod tests { #[test] fn test_serialize_update_operation() { - let insert = DocumentOperation::Update { + let insert = NodeOperation::Update { path: Path(vec![0, 1]), attributes: NodeAttributes::new(), old_attributes: NodeAttributes::new(), @@ -198,7 +198,7 @@ mod tests { #[test] fn test_serialize_text_edit_operation() { - let insert = DocumentOperation::TextEdit { + let insert = NodeOperation::TextEdit { path: Path(vec![0, 1]), delta: Delta::new(), inverted: Delta::new(), diff --git a/shared-lib/lib-ot/src/core/document/node.rs b/shared-lib/lib-ot/src/core/document/node.rs index 82cc1ea4d7..8b2daec19b 100644 --- a/shared-lib/lib-ot/src/core/document/node.rs +++ b/shared-lib/lib-ot/src/core/document/node.rs @@ -18,6 +18,26 @@ impl NodeData { } } +impl std::convert::From for NodeData { + fn from(node: Node) -> Self { + Self { + node_type: node.note_type, + attributes: node.attributes, + delta: node.delta, + } + } +} + +impl std::convert::From<&Node> for NodeData { + fn from(node: &Node) -> Self { + Self { + node_type: node.note_type.clone(), + attributes: node.attributes.clone(), + delta: node.delta.clone(), + } + } +} + #[derive(Clone, Serialize, Deserialize, Eq, PartialEq)] pub struct Node { #[serde(rename = "type")] @@ -41,12 +61,4 @@ impl Node { children: Vec::new(), } } - - pub fn to_node_data(&self) -> NodeData { - NodeData { - node_type: self.note_type.clone(), - attributes: self.attributes.clone(), - delta: self.delta.clone(), - } - } } diff --git a/shared-lib/lib-ot/src/core/document/transaction.rs b/shared-lib/lib-ot/src/core/document/transaction.rs index f26346fe18..52ab794f44 100644 --- a/shared-lib/lib-ot/src/core/document/transaction.rs +++ b/shared-lib/lib-ot/src/core/document/transaction.rs @@ -1,24 +1,24 @@ use crate::core::document::position::Path; -use crate::core::{AttributeValue, DocumentOperation, DocumentTree, Node, NodeAttributes}; +use crate::core::{AttributeValue, Node, NodeAttributes, NodeOperation, NodeTree}; use indextree::NodeId; pub struct Transaction { - pub operations: Vec, + pub operations: Vec, } impl Transaction { - fn new(operations: Vec) -> Transaction { + fn new(operations: Vec) -> Transaction { Transaction { operations } } } pub struct TransactionBuilder<'a> { - document: &'a DocumentTree, - operations: Vec, + document: &'a NodeTree, + operations: Vec, } impl<'a> TransactionBuilder<'a> { - pub fn new(document: &'a DocumentTree) -> TransactionBuilder { + pub fn new(document: &'a NodeTree) -> TransactionBuilder { TransactionBuilder { document, operations: Vec::new(), @@ -38,18 +38,18 @@ impl<'a> TransactionBuilder<'a> { /// // -- 0 (root) /// // 0 -- text_1 /// // 1 -- text_2 - /// use lib_ot::core::{DocumentTree, Node, TransactionBuilder}; - /// let mut document = DocumentTree::new(); - /// let transaction = TransactionBuilder::new(&document) + /// use lib_ot::core::{NodeTree, Node, TransactionBuilder}; + /// let mut node_tree = NodeTree::new(); + /// let transaction = TransactionBuilder::new(&node_tree) /// .insert_nodes_at_path(0,vec![ Node::new("text_1"), Node::new("text_2")]) /// .finalize(); - /// document.apply(transaction).unwrap(); + /// node_tree.apply(transaction).unwrap(); /// - /// document.node_at_path(vec![0, 0]); + /// node_tree.node_at_path(vec![0, 0]); /// ``` /// pub fn insert_nodes_at_path>(self, path: T, nodes: Vec) -> Self { - self.push(DocumentOperation::Insert { + self.push(NodeOperation::Insert { path: path.into(), nodes, }) @@ -68,12 +68,12 @@ impl<'a> TransactionBuilder<'a> { /// // 0 /// // -- 0 /// // |-- text - /// use lib_ot::core::{DocumentTree, Node, TransactionBuilder}; - /// let mut document = DocumentTree::new(); - /// let transaction = TransactionBuilder::new(&document) + /// use lib_ot::core::{NodeTree, Node, TransactionBuilder}; + /// let mut node_tree = NodeTree::new(); + /// let transaction = TransactionBuilder::new(&node_tree) /// .insert_node_at_path(0, Node::new("text")) /// .finalize(); - /// document.apply(transaction).unwrap(); + /// node_tree.apply(transaction).unwrap(); /// ``` /// pub fn insert_node_at_path>(self, path: T, node: Node) -> Self { @@ -92,7 +92,7 @@ impl<'a> TransactionBuilder<'a> { } } - self.push(DocumentOperation::Update { + self.push(NodeOperation::Update { path: path.clone(), attributes, old_attributes, @@ -111,7 +111,7 @@ impl<'a> TransactionBuilder<'a> { node = self.document.following_siblings(node).next().unwrap(); } - self.operations.push(DocumentOperation::Delete { + self.operations.push(NodeOperation::Delete { path: path.clone(), nodes: deleted_nodes, }); @@ -134,7 +134,7 @@ impl<'a> TransactionBuilder<'a> { } } - pub fn push(mut self, op: DocumentOperation) -> Self { + pub fn push(mut self, op: NodeOperation) -> Self { self.operations.push(op); self } diff --git a/shared-lib/lib-ot/tests/node/script.rs b/shared-lib/lib-ot/tests/node/script.rs index 781e537202..c263a1330c 100644 --- a/shared-lib/lib-ot/tests/node/script.rs +++ b/shared-lib/lib-ot/tests/node/script.rs @@ -1,4 +1,4 @@ -use lib_ot::core::{DocumentTree, Node, NodeAttributes, Path, TransactionBuilder}; +use lib_ot::core::{Node, NodeAttributes, NodeTree, Path, TransactionBuilder}; pub enum NodeScript { InsertNode { path: Path, node: Node }, @@ -9,13 +9,13 @@ pub enum NodeScript { } pub struct NodeTest { - node_tree: DocumentTree, + node_tree: NodeTree, } impl NodeTest { pub fn new() -> Self { Self { - node_tree: DocumentTree::new(), + node_tree: NodeTree::new(), } } @@ -53,7 +53,7 @@ impl NodeTest { None => assert!(node_id.is_none()), Some(node_id) => { let node_data = self.node_tree.get_node_data(node_id).cloned(); - assert_eq!(node_data, expected.and_then(|e| Some(e.to_node_data()))); + assert_eq!(node_data, expected.and_then(|e| Some(e.into()))); } } }