refactor: generic insert_nodes method

This commit is contained in:
appflowy 2022-09-08 17:38:11 +08:00
parent 294b1bea13
commit 8f5134305e
5 changed files with 112 additions and 33 deletions

View File

@ -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())?;

View File

@ -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)
}
}

View File

@ -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();

View File

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

View File

@ -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);