feat: apply transactions

This commit is contained in:
Vincent Chan 2022-08-18 17:49:20 +08:00
parent ba160c8026
commit c207bf3679
6 changed files with 58 additions and 28 deletions

View File

@ -1,25 +1,25 @@
use crate::core::document::position::Position; 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}; use indextree::{Arena, NodeId};
pub struct DocumentTree { pub struct DocumentTree {
arena: Arena<NodeData>, pub arena: Arena<NodeData>,
root: NodeId, pub root: NodeId,
} }
impl DocumentTree { impl DocumentTree {
pub fn new() -> DocumentTree { pub fn new() -> DocumentTree {
let mut arena = Arena::new(); let mut arena = Arena::new();
let root = arena.new_node(NodeData::new("root".into())); let root = arena.new_node(NodeData::new("root".into()));
DocumentTree { DocumentTree { arena, root }
arena: Arena::new(),
root,
}
} }
pub fn node_at_path(&self, position: &Position) -> Option<NodeId> { pub fn node_at_path(&self, position: &Position) -> Option<NodeId> {
if position.is_empty() { if position.is_empty() {
return None; return Some(self.root);
} }
let mut iterate_node = self.root; let mut iterate_node = self.root;
@ -93,7 +93,7 @@ impl DocumentTree {
} }
fn apply_op(&mut self, op: &DocumentOperation) { fn apply_op(&mut self, op: &DocumentOperation) {
match op { match op {
DocumentOperation::Insert(op) => self.apply_insert(op), DocumentOperation::Insert(op) => self.apply_insert(op),
DocumentOperation::Update(op) => self.apply_update(op), DocumentOperation::Update(op) => self.apply_update(op),
DocumentOperation::Delete(op) => self.apply_delete(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 last_index = op.path.0[op.path.0.len() - 1];
let parent_node = self.node_at_path(&Position(parent_path.to_vec())); let parent_node = self.node_at_path(&Position(parent_path.to_vec()));
if let Some(parent_node) = parent_node { 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]) { 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 { for id in insert_children {
parent.append(*id, &mut self.arena); parent.append(*id, &mut self.arena);
} }

View File

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

View File

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

View File

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

View File

@ -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 struct Transaction {
pub operations: Vec<DocumentOperation>, pub operations: Vec<DocumentOperation>,
} }
impl Transaction { impl Transaction {
fn new(operations: Vec<DocumentOperation>) -> Transaction { fn new(operations: Vec<DocumentOperation>) -> Transaction {
Transaction { Transaction { operations }
operations,
}
} }
} }
pub struct TransactionBuilder<'a> { pub struct TransactionBuilder<'a> {
@ -23,17 +20,42 @@ impl<'a> TransactionBuilder<'a> {
pub fn new(document: &'a DocumentTree) -> TransactionBuilder { pub fn new(document: &'a DocumentTree) -> TransactionBuilder {
TransactionBuilder { TransactionBuilder {
document, 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) { pub fn push(&mut self, op: DocumentOperation) {
self.operations.push(op); self.operations.push(op);
} }
pub fn finalize(self) -> Transaction { pub fn finalize(self) -> Transaction {
Transaction { Transaction::new(self.operations)
operations: self.operations,
}
} }
} }

View File

@ -1,4 +1,4 @@
use lib_ot::core::{DocumentTree, TransactionBuilder}; use lib_ot::core::{DocumentTree, NodeData, Position, TransactionBuilder};
#[test] #[test]
fn main() { fn main() {
@ -9,7 +9,8 @@ fn main() {
#[test] #[test]
fn test_documents() { fn test_documents() {
let mut document = DocumentTree::new(); 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(); let transaction = tb.finalize();
document.apply(transaction); document.apply(transaction);
} }