浏览代码

feat: apply transactions

Vincent Chan 2 年之前
父节点
当前提交
c207bf3679

+ 17 - 11
shared-lib/lib-ot/src/core/document/document.rs

@@ -1,25 +1,25 @@
 use crate::core::document::position::Position;
-use crate::core::{DeleteOperation, DocumentOperation, InsertOperation, NodeAttributes, NodeData, TextEditOperation, Transaction, UpdateOperation};
+use crate::core::{
+    DeleteOperation, DocumentOperation, InsertOperation, NodeAttributes, NodeData, TextEditOperation, Transaction,
+    UpdateOperation,
+};
 use indextree::{Arena, NodeId};
 
 pub struct DocumentTree {
-    arena: Arena<NodeData>,
-    root: NodeId,
+    pub arena: Arena<NodeData>,
+    pub root: NodeId,
 }
 
 impl DocumentTree {
     pub fn new() -> DocumentTree {
         let mut arena = Arena::new();
         let root = arena.new_node(NodeData::new("root".into()));
-        DocumentTree {
-            arena: Arena::new(),
-            root,
-        }
+        DocumentTree { arena, root }
     }
 
     pub fn node_at_path(&self, position: &Position) -> Option<NodeId> {
         if position.is_empty() {
-            return None;
+            return Some(self.root);
         }
 
         let mut iterate_node = self.root;
@@ -93,7 +93,7 @@ impl DocumentTree {
     }
 
     fn apply_op(&mut self, op: &DocumentOperation) {
-        match op  {
+        match op {
             DocumentOperation::Insert(op) => self.apply_insert(op),
             DocumentOperation::Update(op) => self.apply_update(op),
             DocumentOperation::Delete(op) => self.apply_delete(op),
@@ -106,12 +106,18 @@ impl DocumentTree {
         let last_index = op.path.0[op.path.0.len() - 1];
         let parent_node = self.node_at_path(&Position(parent_path.to_vec()));
         if let Some(parent_node) = parent_node {
-            self.insert_child_at_index(parent_node, last_index, &op.nodes);
+            let mut inserted_nodes = Vec::new();
+
+            for node in &op.nodes {
+                inserted_nodes.push(self.arena.new_node(node.clone()));
+            }
+
+            self.insert_child_at_index(parent_node, last_index, &inserted_nodes);
         }
     }
 
     fn insert_child_at_index(&mut self, parent: NodeId, index: usize, insert_children: &[NodeId]) {
-        if index == 0 && insert_children.len() == 0 {
+        if index == 0 && parent.children(&self.arena).next().is_none() {
             for id in insert_children {
                 parent.append(*id, &mut self.arena);
             }

+ 3 - 4
shared-lib/lib-ot/src/core/document/document_operation.rs

@@ -1,6 +1,5 @@
 use crate::core::document::position::Position;
-use crate::core::{NodeAttributes, TextDelta};
-use indextree::NodeId;
+use crate::core::{NodeAttributes, NodeData, TextDelta};
 
 pub enum DocumentOperation {
     Insert(InsertOperation),
@@ -36,7 +35,7 @@ impl DocumentOperation {
 
 pub struct InsertOperation {
     pub path: Position,
-    pub nodes: Vec<NodeId>,
+    pub nodes: Vec<NodeData>,
 }
 
 pub struct UpdateOperation {
@@ -47,7 +46,7 @@ pub struct UpdateOperation {
 
 pub struct DeleteOperation {
     pub path: Position,
-    pub nodes: Vec<NodeId>,
+    pub nodes: Vec<NodeData>,
 }
 
 pub struct TextEditOperation {

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

@@ -9,4 +9,5 @@ pub use attributes::*;
 pub use document::*;
 pub use document_operation::*;
 pub use node::*;
+pub use position::*;
 pub use transaction::*;

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

@@ -1,6 +1,7 @@
+use crate::core::{NodeAttributes, TextDelta};
 use std::cell::RefCell;
-use crate::core::{TextDelta, NodeAttributes};
 
+#[derive(Clone)]
 pub struct NodeData {
     pub node_type: String,
     pub attributes: RefCell<NodeAttributes>,

+ 32 - 10
shared-lib/lib-ot/src/core/document/transaction.rs

@@ -1,17 +1,14 @@
-use crate::core::{DocumentOperation, DocumentTree};
+use crate::core::document::position::Position;
+use crate::core::{DeleteOperation, DocumentOperation, DocumentTree, InsertOperation, NodeData};
 
 pub struct Transaction {
     pub operations: Vec<DocumentOperation>,
 }
 
 impl Transaction {
-
     fn new(operations: Vec<DocumentOperation>) -> Transaction {
-        Transaction {
-            operations,
-        }
+        Transaction { operations }
     }
-
 }
 
 pub struct TransactionBuilder<'a> {
@@ -23,17 +20,42 @@ impl<'a> TransactionBuilder<'a> {
     pub fn new(document: &'a DocumentTree) -> TransactionBuilder {
         TransactionBuilder {
             document,
-            operations: Vec::new()
+            operations: Vec::new(),
         }
     }
 
+    pub fn insert_nodes(&mut self, path: &Position, nodes: &[NodeData]) {
+        self.push(DocumentOperation::Insert(InsertOperation {
+            path: path.clone(),
+            nodes: nodes.to_vec(),
+        }));
+    }
+
+    pub fn delete_node(&mut self, path: &Position) {
+        self.delete_nodes(path, 1);
+    }
+
+    pub fn delete_nodes(&mut self, path: &Position, length: usize) {
+        let mut node = self.document.node_at_path(path).unwrap();
+        let mut deleted_nodes: Vec<NodeData> = Vec::new();
+
+        for _ in 0..length {
+            let data = self.document.arena.get(node).unwrap();
+            deleted_nodes.push(data.get().clone());
+            node = node.following_siblings(&self.document.arena).next().unwrap();
+        }
+
+        self.operations.push(DocumentOperation::Delete(DeleteOperation {
+            path: path.clone(),
+            nodes: deleted_nodes,
+        }))
+    }
+
     pub fn push(&mut self, op: DocumentOperation) {
         self.operations.push(op);
     }
 
     pub fn finalize(self) -> Transaction {
-        Transaction {
-            operations: self.operations,
-        }
+        Transaction::new(self.operations)
     }
 }

+ 3 - 2
shared-lib/lib-ot/tests/main.rs

@@ -1,4 +1,4 @@
-use lib_ot::core::{DocumentTree, TransactionBuilder};
+use lib_ot::core::{DocumentTree, NodeData, Position, TransactionBuilder};
 
 #[test]
 fn main() {
@@ -9,7 +9,8 @@ fn main() {
 #[test]
 fn test_documents() {
     let mut document = DocumentTree::new();
-    let tb = TransactionBuilder::new(&document);
+    let mut tb = TransactionBuilder::new(&document);
+    tb.insert_nodes(&Position(vec![0]), &vec![NodeData::new("type")]);
     let transaction = tb.finalize();
     document.apply(transaction);
 }