Skip to content

Commit b0bafff

Browse files
committed
feat: introduce error to apply method
1 parent ef185cd commit b0bafff

File tree

7 files changed

+193
-134
lines changed

7 files changed

+193
-134
lines changed

frontend/rust-lib/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared-lib/lib-ot/src/core/document/document.rs

Lines changed: 82 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::core::document::position::Position;
2-
use crate::core::{
3-
DeleteOperation, DocumentOperation, InsertOperation, NodeAttributes, NodeData, TextEditOperation, Transaction,
4-
UpdateOperation,
5-
};
2+
use crate::core::{DocumentOperation, NodeAttributes, NodeData, OperationTransform, TextDelta, Transaction};
3+
use crate::errors::{ErrorBuilder, OTError, OTErrorCode};
64
use indextree::{Arena, NodeId};
75

86
pub struct DocumentTree {
@@ -86,42 +84,48 @@ impl DocumentTree {
8684
None
8785
}
8886

89-
pub fn apply(&mut self, transaction: Transaction) {
87+
pub fn apply(&mut self, transaction: Transaction) -> Result<(), OTError> {
9088
for op in &transaction.operations {
91-
self.apply_op(op);
89+
self.apply_op(op)?;
9290
}
91+
Ok(())
9392
}
9493

95-
fn apply_op(&mut self, op: &DocumentOperation) {
94+
fn apply_op(&mut self, op: &DocumentOperation) -> Result<(), OTError> {
9695
match op {
97-
DocumentOperation::Insert(op) => self.apply_insert(op),
98-
DocumentOperation::Update(op) => self.apply_update(op),
99-
DocumentOperation::Delete(op) => self.apply_delete(op),
100-
DocumentOperation::TextEdit(op) => self.apply_text_edit(op),
96+
DocumentOperation::Insert { path, nodes } => self.apply_insert(path, nodes),
97+
DocumentOperation::Update { path, attributes, .. } => self.apply_update(path, attributes),
98+
DocumentOperation::Delete { path, nodes } => self.apply_delete(path, nodes.len()),
99+
DocumentOperation::TextEdit { path, delta, .. } => self.apply_text_edit(path, delta),
101100
}
102101
}
103102

104-
fn apply_insert(&mut self, op: &InsertOperation) {
105-
let parent_path = &op.path.0[0..(op.path.0.len() - 1)];
106-
let last_index = op.path.0[op.path.0.len() - 1];
107-
let parent_node = self.node_at_path(&Position(parent_path.to_vec()));
108-
if let Some(parent_node) = parent_node {
109-
let mut inserted_nodes = Vec::new();
103+
fn apply_insert(&mut self, path: &Position, nodes: &Vec<NodeData>) -> Result<(), OTError> {
104+
let parent_path = &path.0[0..(path.0.len() - 1)];
105+
let last_index = path.0[path.0.len() - 1];
106+
let parent_node = self
107+
.node_at_path(&Position(parent_path.to_vec()))
108+
.ok_or(ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
109+
let mut inserted_nodes = Vec::new();
110110

111-
for node in &op.nodes {
112-
inserted_nodes.push(self.arena.new_node(node.clone()));
113-
}
114-
115-
self.insert_child_at_index(parent_node, last_index, &inserted_nodes);
111+
for node in nodes {
112+
inserted_nodes.push(self.arena.new_node(node.clone()));
116113
}
114+
115+
self.insert_child_at_index(parent_node, last_index, &inserted_nodes)
117116
}
118117

119-
fn insert_child_at_index(&mut self, parent: NodeId, index: usize, insert_children: &[NodeId]) {
118+
fn insert_child_at_index(
119+
&mut self,
120+
parent: NodeId,
121+
index: usize,
122+
insert_children: &[NodeId],
123+
) -> Result<(), OTError> {
120124
if index == 0 && parent.children(&self.arena).next().is_none() {
121125
for id in insert_children {
122126
parent.append(*id, &mut self.arena);
123127
}
124-
return;
128+
return Ok(());
125129
}
126130

127131
let children_length = parent.children(&self.arena).fold(0, |counter, _| counter + 1);
@@ -130,32 +134,72 @@ impl DocumentTree {
130134
for id in insert_children {
131135
parent.append(*id, &mut self.arena);
132136
}
133-
return;
137+
return Ok(());
134138
}
135139

136-
let node_to_insert = self.child_at_index_of_path(parent, index).unwrap();
140+
let node_to_insert = self
141+
.child_at_index_of_path(parent, index)
142+
.ok_or(ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
137143

138144
for id in insert_children {
139145
node_to_insert.insert_before(*id, &mut self.arena);
140146
}
147+
Ok(())
141148
}
142149

143-
fn apply_update(&self, op: &UpdateOperation) {
144-
let update_node = self.node_at_path(&op.path).unwrap();
145-
let node_data = self.arena.get(update_node).unwrap();
146-
let new_attributes = {
147-
let old_attributes = node_data.get().attributes.borrow();
148-
NodeAttributes::compose(&old_attributes, &op.attributes)
150+
fn apply_update(&mut self, path: &Position, attributes: &NodeAttributes) -> Result<(), OTError> {
151+
let update_node = self
152+
.node_at_path(path)
153+
.ok_or(ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
154+
let node_data = self.arena.get_mut(update_node).unwrap();
155+
// let new_node = NodeData {
156+
// ..node_data.get().clone()
157+
// attributes:
158+
// };
159+
let new_node = {
160+
let old_attributes = &node_data.get().attributes;
161+
let new_attributes = NodeAttributes::compose(&old_attributes, attributes);
162+
NodeData {
163+
attributes: new_attributes,
164+
..node_data.get().clone()
165+
}
149166
};
150-
node_data.get().attributes.replace(new_attributes);
167+
*node_data.get_mut() = new_node;
168+
Ok(())
151169
}
152170

153-
fn apply_delete(&mut self, op: &DeleteOperation) {
154-
let update_node = self.node_at_path(&op.path).unwrap();
155-
update_node.remove_subtree(&mut self.arena);
171+
fn apply_delete(&mut self, path: &Position, len: usize) -> Result<(), OTError> {
172+
let mut update_node = self
173+
.node_at_path(path)
174+
.ok_or(ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
175+
for _ in 0..len {
176+
let next = update_node.following_siblings(&self.arena).next();
177+
update_node.remove_subtree(&mut self.arena);
178+
if let Some(next_id) = next {
179+
update_node = next_id;
180+
} else {
181+
break;
182+
}
183+
}
184+
Ok(())
156185
}
157186

158-
fn apply_text_edit(&self, _op: &TextEditOperation) {
159-
unimplemented!()
187+
fn apply_text_edit(&mut self, path: &Position, delta: &TextDelta) -> Result<(), OTError> {
188+
let edit_node = self
189+
.node_at_path(path)
190+
.ok_or(ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
191+
let node_data = self.arena.get_mut(edit_node).unwrap();
192+
let new_delta = if let Some(old_delta) = &node_data.get().delta {
193+
Some(old_delta.compose(delta)?)
194+
} else {
195+
None
196+
};
197+
if let Some(new_delta) = new_delta {
198+
*node_data.get_mut() = NodeData {
199+
delta: Some(new_delta),
200+
..node_data.get().clone()
201+
};
202+
};
203+
Ok(())
160204
}
161205
}

shared-lib/lib-ot/src/core/document/document_operation.rs

Lines changed: 66 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,102 +3,98 @@ use crate::core::{NodeAttributes, NodeData, TextDelta};
33

44
#[derive(Clone)]
55
pub enum DocumentOperation {
6-
Insert(InsertOperation),
7-
Update(UpdateOperation),
8-
Delete(DeleteOperation),
9-
TextEdit(TextEditOperation),
6+
Insert {
7+
path: Position,
8+
nodes: Vec<NodeData>,
9+
},
10+
Update {
11+
path: Position,
12+
attributes: NodeAttributes,
13+
old_attributes: NodeAttributes,
14+
},
15+
Delete {
16+
path: Position,
17+
nodes: Vec<NodeData>,
18+
},
19+
TextEdit {
20+
path: Position,
21+
delta: TextDelta,
22+
inverted: TextDelta,
23+
},
1024
}
1125

1226
impl DocumentOperation {
1327
pub fn path(&self) -> &Position {
1428
match self {
15-
DocumentOperation::Insert(insert) => &insert.path,
16-
DocumentOperation::Update(update) => &update.path,
17-
DocumentOperation::Delete(delete) => &delete.path,
18-
DocumentOperation::TextEdit(text_edit) => &text_edit.path,
29+
DocumentOperation::Insert { path, .. } => path,
30+
DocumentOperation::Update { path, .. } => path,
31+
DocumentOperation::Delete { path, .. } => path,
32+
DocumentOperation::TextEdit { path, .. } => path,
1933
}
2034
}
2135
pub fn invert(&self) -> DocumentOperation {
2236
match self {
23-
DocumentOperation::Insert(insert_operation) => DocumentOperation::Delete(DeleteOperation {
24-
path: insert_operation.path.clone(),
25-
nodes: insert_operation.nodes.clone(),
26-
}),
27-
DocumentOperation::Update(update_operation) => DocumentOperation::Update(UpdateOperation {
28-
path: update_operation.path.clone(),
29-
attributes: update_operation.old_attributes.clone(),
30-
old_attributes: update_operation.attributes.clone(),
31-
}),
32-
DocumentOperation::Delete(delete_operation) => DocumentOperation::Insert(InsertOperation {
33-
path: delete_operation.path.clone(),
34-
nodes: delete_operation.nodes.clone(),
35-
}),
36-
DocumentOperation::TextEdit(text_edit_operation) => DocumentOperation::TextEdit(TextEditOperation {
37-
path: text_edit_operation.path.clone(),
38-
delta: text_edit_operation.inverted.clone(),
39-
inverted: text_edit_operation.delta.clone(),
40-
}),
37+
DocumentOperation::Insert { path, nodes } => DocumentOperation::Delete {
38+
path: path.clone(),
39+
nodes: nodes.clone(),
40+
},
41+
DocumentOperation::Update {
42+
path,
43+
attributes,
44+
old_attributes,
45+
} => DocumentOperation::Update {
46+
path: path.clone(),
47+
attributes: old_attributes.clone(),
48+
old_attributes: attributes.clone(),
49+
},
50+
DocumentOperation::Delete { path, nodes } => DocumentOperation::Insert {
51+
path: path.clone(),
52+
nodes: nodes.clone(),
53+
},
54+
DocumentOperation::TextEdit { path, delta, inverted } => DocumentOperation::TextEdit {
55+
path: path.clone(),
56+
delta: inverted.clone(),
57+
inverted: delta.clone(),
58+
},
4159
}
4260
}
4361
pub fn clone_with_new_path(&self, path: Position) -> DocumentOperation {
4462
match self {
45-
DocumentOperation::Insert(insert) => DocumentOperation::Insert(InsertOperation {
63+
DocumentOperation::Insert { nodes, .. } => DocumentOperation::Insert {
4664
path,
47-
nodes: insert.nodes.clone(),
48-
}),
49-
DocumentOperation::Update(update) => DocumentOperation::Update(UpdateOperation {
65+
nodes: nodes.clone(),
66+
},
67+
DocumentOperation::Update {
68+
attributes,
69+
old_attributes,
70+
..
71+
} => DocumentOperation::Update {
5072
path,
51-
attributes: update.attributes.clone(),
52-
old_attributes: update.old_attributes.clone(),
53-
}),
54-
DocumentOperation::Delete(delete) => DocumentOperation::Delete(DeleteOperation {
73+
attributes: attributes.clone(),
74+
old_attributes: old_attributes.clone(),
75+
},
76+
DocumentOperation::Delete { nodes, .. } => DocumentOperation::Delete {
5577
path,
56-
nodes: delete.nodes.clone(),
57-
}),
58-
DocumentOperation::TextEdit(text_edit) => DocumentOperation::TextEdit(TextEditOperation {
78+
nodes: nodes.clone(),
79+
},
80+
DocumentOperation::TextEdit { delta, inverted, .. } => DocumentOperation::TextEdit {
5981
path,
60-
delta: text_edit.delta.clone(),
61-
inverted: text_edit.inverted.clone(),
62-
}),
82+
delta: delta.clone(),
83+
inverted: inverted.clone(),
84+
},
6385
}
6486
}
6587
pub fn transform(a: &DocumentOperation, b: &DocumentOperation) -> DocumentOperation {
6688
match a {
67-
DocumentOperation::Insert(insert_op) => {
68-
let new_path = Position::transform(a.path(), b.path(), insert_op.nodes.len() as i64);
89+
DocumentOperation::Insert { path: a_path, nodes } => {
90+
let new_path = Position::transform(a_path, b.path(), nodes.len() as i64);
6991
b.clone_with_new_path(new_path)
7092
}
71-
DocumentOperation::Delete(delete_op) => {
72-
let new_path = Position::transform(a.path(), b.path(), delete_op.nodes.len() as i64);
93+
DocumentOperation::Delete { path: a_path, nodes } => {
94+
let new_path = Position::transform(a_path, b.path(), nodes.len() as i64);
7395
b.clone_with_new_path(new_path)
7496
}
7597
_ => b.clone(),
7698
}
7799
}
78100
}
79-
80-
#[derive(Clone)]
81-
pub struct InsertOperation {
82-
pub path: Position,
83-
pub nodes: Vec<NodeData>,
84-
}
85-
86-
#[derive(Clone)]
87-
pub struct UpdateOperation {
88-
pub path: Position,
89-
pub attributes: NodeAttributes,
90-
pub old_attributes: NodeAttributes,
91-
}
92-
93-
#[derive(Clone)]
94-
pub struct DeleteOperation {
95-
pub path: Position,
96-
pub nodes: Vec<NodeData>,
97-
}
98-
99-
#[derive(Clone)]
100-
pub struct TextEditOperation {
101-
pub path: Position,
102-
pub delta: TextDelta,
103-
pub inverted: TextDelta,
104-
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
use crate::core::{NodeAttributes, TextDelta};
2-
use std::cell::RefCell;
32

43
#[derive(Clone)]
54
pub struct NodeData {
65
pub node_type: String,
7-
pub attributes: RefCell<NodeAttributes>,
8-
pub delta: RefCell<Option<TextDelta>>,
6+
pub attributes: NodeAttributes,
7+
pub delta: Option<TextDelta>,
98
}
109

1110
impl NodeData {
1211
pub fn new(node_type: &str) -> NodeData {
1312
NodeData {
1413
node_type: node_type.into(),
15-
attributes: RefCell::new(NodeAttributes::new()),
16-
delta: RefCell::new(None),
14+
attributes: NodeAttributes::new(),
15+
delta: None,
1716
}
1817
}
1918
}

0 commit comments

Comments
 (0)