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 7b7b0c4a62..ff1a968af5 100644 --- a/shared-lib/lib-ot/src/core/document/document_operation.rs +++ b/shared-lib/lib-ot/src/core/document/document_operation.rs @@ -1,6 +1,7 @@ use crate::core::document::position::Position; use crate::core::{NodeAttributes, NodeData, TextDelta}; +#[derive(Clone)] pub enum DocumentOperation { Insert(InsertOperation), Update(UpdateOperation), @@ -31,24 +32,31 @@ impl DocumentOperation { }), } } + pub fn transform(_a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation { + b.clone() + } } +#[derive(Clone)] pub struct InsertOperation { pub path: Position, pub nodes: Vec, } +#[derive(Clone)] pub struct UpdateOperation { pub path: Position, pub attributes: NodeAttributes, pub old_attributes: NodeAttributes, } +#[derive(Clone)] pub struct DeleteOperation { pub path: Position, pub nodes: Vec, } +#[derive(Clone)] pub struct TextEditOperation { pub path: Position, pub delta: TextDelta, diff --git a/shared-lib/lib-ot/src/core/document/position.rs b/shared-lib/lib-ot/src/core/document/position.rs index 34e0c784d5..b463f207da 100644 --- a/shared-lib/lib-ot/src/core/document/position.rs +++ b/shared-lib/lib-ot/src/core/document/position.rs @@ -5,6 +5,38 @@ impl Position { pub fn is_empty(&self) -> bool { self.0.is_empty() } + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl Position { + // delta is default to be 1 + pub fn transform(pre_insert_path: &Position, b: &Position, delta: usize) -> Position { + if pre_insert_path.len() > b.len() { + return b.clone(); + } + if pre_insert_path.is_empty() || b.is_empty() { + return b.clone(); + } + // check the prefix + for i in 0..(pre_insert_path.len()) { + if pre_insert_path.0[i] != b.0[i] { + return b.clone(); + } + } + let mut prefix: Vec = pre_insert_path.0[0..(pre_insert_path.len() - 1)].into(); + let mut suffix: Vec = b.0[pre_insert_path.0.len()..].into(); + let prev_insert_last: usize = *pre_insert_path.0.last().unwrap(); + let b_at_index = b.0[pre_insert_path.0.len() - 1]; + if prev_insert_last <= b_at_index { + prefix.push(b_at_index + delta); + } else { + prefix.push(b_at_index); + } + prefix.append(&mut suffix); + return Position(prefix); + } } impl From> for Position { diff --git a/shared-lib/lib-ot/src/core/document/transaction.rs b/shared-lib/lib-ot/src/core/document/transaction.rs index f240b8ea89..c0e7cc3243 100644 --- a/shared-lib/lib-ot/src/core/document/transaction.rs +++ b/shared-lib/lib-ot/src/core/document/transaction.rs @@ -1,6 +1,8 @@ -use std::collections::HashMap; use crate::core::document::position::Position; -use crate::core::{DeleteOperation, DocumentOperation, DocumentTree, InsertOperation, NodeAttributes, NodeData, UpdateOperation}; +use crate::core::{ + DeleteOperation, DocumentOperation, DocumentTree, InsertOperation, NodeAttributes, NodeData, UpdateOperation, +}; +use std::collections::HashMap; pub struct Transaction { pub operations: Vec, diff --git a/shared-lib/lib-ot/tests/main.rs b/shared-lib/lib-ot/tests/main.rs index c2e0226eb6..f6d5aa6ace 100644 --- a/shared-lib/lib-ot/tests/main.rs +++ b/shared-lib/lib-ot/tests/main.rs @@ -1,5 +1,5 @@ -use std::collections::HashMap; use lib_ot::core::{DocumentTree, NodeData, TransactionBuilder}; +use std::collections::HashMap; #[test] fn main() { @@ -21,9 +21,10 @@ fn test_documents() { assert_eq!(node_data.node_type, "text"); let mut tb = TransactionBuilder::new(&document); - tb.update_attributes(&vec![0].into(), HashMap::from([ - ("subtype".into(), Some("bullet-list".into())), - ])); + tb.update_attributes( + &vec![0].into(), + HashMap::from([("subtype".into(), Some("bullet-list".into()))]), + ); let transaction = tb.finalize(); document.apply(transaction);