瀏覽代碼

refactor: generic insert_nodes method

appflowy 2 年之前
父節點
當前提交
8f5134305e

+ 6 - 1
shared-lib/lib-ot/src/core/document/document.rs

@@ -23,7 +23,8 @@ impl DocumentTree {
         DocumentTree { arena, root }
     }
 
-    pub fn node_at_path(&self, path: &Path) -> Option<NodeId> {
+    pub fn node_at_path<T: Into<Path>>(&self, path: T) -> Option<NodeId> {
+        let path = path.into();
         if path.is_empty() {
             return Some(self.root);
         }
@@ -120,8 +121,12 @@ impl DocumentTree {
     }
 
     fn apply_insert(&mut self, path: &Path, nodes: &[NodeSubTree]) -> Result<(), OTError> {
+
+
         let parent_path = &path.0[0..(path.0.len() - 1)];
         let last_index = path.0[path.0.len() - 1];
+
+
         let parent_node = self
             .node_at_path(&Path(parent_path.to_vec()))
             .ok_or_else(|| ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;

+ 28 - 9
shared-lib/lib-ot/src/core/document/position.rs

@@ -9,12 +9,37 @@ impl std::ops::Deref for Path {
     }
 }
 
-impl AsRef<Path> for usize {
-    fn as_ref(&self) -> &Path {
-        todo!()
+impl std::convert::Into<Path> for usize {
+    fn into(self) -> Path {
+        Path(vec![self])
     }
 }
 
+impl std::convert::Into<Path> for &usize {
+    fn into(self) -> Path {
+        Path(vec![*self])
+    }
+}
+
+impl std::convert::Into<Path> for &Path {
+    fn into(self) -> Path {
+       self.clone()
+    }
+}
+
+impl From<Vec<usize>> for Path {
+    fn from(v: Vec<usize>) -> Self {
+        Path(v)
+    }
+}
+
+impl From<&Vec<usize>> for Path {
+    fn from(values: &Vec<usize>) -> Self {
+        Path(values.clone())
+    }
+}
+
+
 impl Path {
     // delta is default to be 1
     pub fn transform(pre_insert_path: &Path, b: &Path, offset: i64) -> Path {
@@ -44,9 +69,3 @@ impl Path {
         Path(prefix)
     }
 }
-
-impl From<Vec<usize>> for Path {
-    fn from(v: Vec<usize>) -> Self {
-        Path(v)
-    }
-}

+ 57 - 3
shared-lib/lib-ot/src/core/document/transaction.rs

@@ -26,13 +26,67 @@ impl<'a> TransactionBuilder<'a> {
         }
     }
 
-    pub fn insert_nodes_at_path(&mut self, path: &Path, nodes: &[NodeSubTree]) {
+
+    ///
+    ///
+    /// # Arguments
+    ///
+    /// * `path`: the path that is used to save the nodes
+    /// * `nodes`: the nodes you will be save in the path
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// // 0
+    /// // -- 0
+    /// //    |-- text_1
+    /// //    |-- text_2
+    /// use lib_ot::core::{DocumentTree, NodeSubTree, TransactionBuilder};
+    /// let mut document = DocumentTree::new();
+    /// let transaction = {
+    ///     let mut tb = TransactionBuilder::new(&document);
+    ///     tb.insert_nodes_at_path(0,vec![ NodeSubTree::new("text_1"),  NodeSubTree::new("text_2")]);
+    ///     tb.finalize()
+    /// };
+    ///  document.apply(transaction).unwrap();
+    ///
+    ///  document.node_at_path(vec![0, 0]);
+    /// ```
+    ///
+    pub fn insert_nodes_at_path<T: Into<Path>>(&mut self, path: T, nodes: Vec<NodeSubTree>) {
         self.push(DocumentOperation::Insert {
-            path: path.clone(),
-            nodes: nodes.to_vec(),
+            path: path.into(),
+            nodes,
         });
     }
 
+    ///
+    ///
+    /// # Arguments
+    ///
+    /// * `path`: the path that is used to save the nodes
+    /// * `node`: the node data will be saved in the path
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// // 0
+    /// // -- 0
+    /// //    |-- text
+    /// use lib_ot::core::{DocumentTree, NodeSubTree, TransactionBuilder};
+    /// let mut document = DocumentTree::new();
+    /// let transaction = {
+    ///     let mut tb = TransactionBuilder::new(&document);
+    ///     tb.insert_node_at_path(0, NodeSubTree::new("text"));
+    ///     tb.finalize()
+    /// };
+    ///  document.apply(transaction).unwrap();
+    /// ```
+    ///
+    pub fn insert_node_at_path<T: Into<Path>>(&mut self, path: T, node: NodeSubTree) {
+       self.insert_nodes_at_path(path, vec![node]);
+    }
+
     pub fn update_attributes_at_path(&mut self, path: &Path, attributes: HashMap<String, Option<String>>) {
         let mut old_attributes: HashMap<String, Option<String>> = HashMap::new();
         let node = self.document.node_at_path(path).unwrap();

+ 1 - 0
shared-lib/lib-ot/src/errors.rs

@@ -75,6 +75,7 @@ pub enum OTErrorCode {
     RevisionIDConflict,
     Internal,
     PathNotFound,
+    PathIsEmpty,
 }
 
 pub struct ErrorBuilder {

+ 20 - 20
shared-lib/lib-ot/tests/main.rs

@@ -13,13 +13,13 @@ fn test_documents() {
     let mut document = DocumentTree::new();
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(&vec![0].into(), &[NodeSubTree::new("text")]);
+        tb.insert_node_at_path(0, NodeSubTree::new("text"));
         tb.finalize()
     };
     document.apply(transaction).unwrap();
 
-    assert!(document.node_at_path(&vec![0].into()).is_some());
-    let node = document.node_at_path(&vec![0].into()).unwrap();
+    assert!(document.node_at_path(0).is_some());
+    let node = document.node_at_path(0).unwrap();
     let node_data = document.arena.get(node).unwrap().get();
     assert_eq!(node_data.node_type, "text");
 
@@ -39,7 +39,7 @@ fn test_documents() {
         tb.finalize()
     };
     document.apply(transaction).unwrap();
-    assert!(document.node_at_path(&vec![0].into()).is_none());
+    assert!(document.node_at_path(0).is_none());
 }
 
 #[test]
@@ -47,16 +47,16 @@ fn test_inserts_nodes() {
     let mut document = DocumentTree::new();
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(&vec![0].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![1].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![2].into(), &[NodeSubTree::new("text")]);
+        tb.insert_node_at_path(0, NodeSubTree::new("text"));
+        tb.insert_node_at_path(1, NodeSubTree::new("text"));
+        tb.insert_node_at_path(2, NodeSubTree::new("text"));
         tb.finalize()
     };
     document.apply(transaction).unwrap();
 
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(&vec![1].into(), &[NodeSubTree::new("text")]);
+        tb.insert_node_at_path(1, NodeSubTree::new("text"));
         tb.finalize()
     };
     document.apply(transaction).unwrap();
@@ -67,14 +67,14 @@ fn test_inserts_subtrees() {
     let mut document = DocumentTree::new();
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(
-            &vec![0].into(),
-            &[NodeSubTree {
+        tb.insert_node_at_path(
+            0,
+            NodeSubTree {
                 node_type: "text".into(),
                 attributes: NodeAttributes::new(),
                 delta: None,
                 children: vec![NodeSubTree::new("image")],
-            }],
+            },
         );
         tb.finalize()
     };
@@ -90,9 +90,9 @@ fn test_update_nodes() {
     let mut document = DocumentTree::new();
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(&vec![0].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![1].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![2].into(), &[NodeSubTree::new("text")]);
+        tb.insert_node_at_path(&vec![0], NodeSubTree::new("text"));
+        tb.insert_node_at_path(&vec![1], NodeSubTree::new("text"));
+        tb.insert_node_at_path(vec![2], NodeSubTree::new("text"));
         tb.finalize()
     };
     document.apply(transaction).unwrap();
@@ -115,9 +115,9 @@ fn test_delete_nodes() {
     let mut document = DocumentTree::new();
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(&vec![0].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![1].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![2].into(), &[NodeSubTree::new("text")]);
+        tb.insert_node_at_path(0, NodeSubTree::new("text"));
+        tb.insert_node_at_path(1, NodeSubTree::new("text"));
+        tb.insert_node_at_path(2, NodeSubTree::new("text"));
         tb.finalize()
     };
     document.apply(transaction).unwrap();
@@ -138,8 +138,8 @@ fn test_errors() {
     let mut document = DocumentTree::new();
     let transaction = {
         let mut tb = TransactionBuilder::new(&document);
-        tb.insert_nodes_at_path(&vec![0].into(), &[NodeSubTree::new("text")]);
-        tb.insert_nodes_at_path(&vec![100].into(), &[NodeSubTree::new("text")]);
+        tb.insert_node_at_path(0, NodeSubTree::new("text"));
+        tb.insert_node_at_path(100, NodeSubTree::new("text"));
         tb.finalize()
     };
     let result = document.apply(transaction);