mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-11-16 18:37:40 +00:00
chore: private the Arena
This commit is contained in:
parent
e711bfce1d
commit
9974539946
@ -3,10 +3,10 @@ use crate::core::{
|
|||||||
DocumentOperation, NodeAttributes, NodeData, NodeSubTree, OperationTransform, TextDelta, Transaction,
|
DocumentOperation, NodeAttributes, NodeData, NodeSubTree, OperationTransform, TextDelta, Transaction,
|
||||||
};
|
};
|
||||||
use crate::errors::{ErrorBuilder, OTError, OTErrorCode};
|
use crate::errors::{ErrorBuilder, OTError, OTErrorCode};
|
||||||
use indextree::{Arena, NodeId};
|
use indextree::{Arena, Children, FollowingSiblings, Node, NodeId};
|
||||||
|
|
||||||
pub struct DocumentTree {
|
pub struct DocumentTree {
|
||||||
pub arena: Arena<NodeData>,
|
arena: Arena<NodeData>,
|
||||||
pub root: NodeId,
|
pub root: NodeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ impl DocumentTree {
|
|||||||
|
|
||||||
let mut iterate_node = self.root;
|
let mut iterate_node = self.root;
|
||||||
for id in path.iter() {
|
for id in path.iter() {
|
||||||
iterate_node = self.child_at_index_of_path(iterate_node, *id)?;
|
iterate_node = self.child_from_node_with_index(iterate_node, *id)?;
|
||||||
}
|
}
|
||||||
Some(iterate_node)
|
Some(iterate_node)
|
||||||
}
|
}
|
||||||
@ -84,9 +84,30 @@ impl DocumentTree {
|
|||||||
counter
|
counter
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn child_at_index_of_path(&self, at_node: NodeId, index: usize) -> Option<NodeId> {
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `at_node`:
|
||||||
|
/// * `index`:
|
||||||
|
///
|
||||||
|
/// returns: Option<NodeId>
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use lib_ot::core::{DocumentOperation, DocumentTree, NodeSubTree, Path};
|
||||||
|
/// let node = NodeSubTree::new("text");
|
||||||
|
/// let inserted_path: Path = vec![0].into();
|
||||||
|
///
|
||||||
|
/// let mut document = DocumentTree::new();
|
||||||
|
/// document.apply_op(&DocumentOperation::Insert {path: inserted_path.clone(),nodes: vec![node.clone()] }).unwrap();
|
||||||
|
///
|
||||||
|
/// let inserted_note = document.node_at_path(&inserted_path).unwrap();
|
||||||
|
/// let inserted_data = document.get_node_data(inserted_note).unwrap();
|
||||||
|
/// assert_eq!(inserted_data.node_type, node.node_type);
|
||||||
|
/// ```
|
||||||
|
pub fn child_from_node_with_index(&self, at_node: NodeId, index: usize) -> Option<NodeId> {
|
||||||
let children = at_node.children(&self.arena);
|
let children = at_node.children(&self.arena);
|
||||||
|
|
||||||
for (counter, child) in children.enumerate() {
|
for (counter, child) in children.enumerate() {
|
||||||
if counter == index {
|
if counter == index {
|
||||||
return Some(child);
|
return Some(child);
|
||||||
@ -96,6 +117,22 @@ impl DocumentTree {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn children_from_node(&self, node_id: NodeId) -> Children<'_, NodeData> {
|
||||||
|
node_id.children(&self.arena)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_node_data(&self, node_id: NodeId) -> Option<&NodeData> {
|
||||||
|
Some(self.arena.get(node_id)?.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn number_of_children(&self) -> usize {
|
||||||
|
self.root.children(&self.arena).fold(0, |count, _| count + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn following_siblings(&self, node_id: NodeId) -> FollowingSiblings<'_, NodeData> {
|
||||||
|
node_id.following_siblings(&self.arena)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn apply(&mut self, transaction: Transaction) -> Result<(), OTError> {
|
pub fn apply(&mut self, transaction: Transaction) -> Result<(), OTError> {
|
||||||
for op in &transaction.operations {
|
for op in &transaction.operations {
|
||||||
self.apply_op(op)?;
|
self.apply_op(op)?;
|
||||||
@ -146,7 +183,7 @@ impl DocumentTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let node_to_insert = self
|
let node_to_insert = self
|
||||||
.child_at_index_of_path(parent, index)
|
.child_from_node_with_index(parent, index)
|
||||||
.ok_or_else(|| ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
|
.ok_or_else(|| ErrorBuilder::new(OTErrorCode::PathNotFound).build())?;
|
||||||
|
|
||||||
self.insert_subtree_before(&node_to_insert, insert_children);
|
self.insert_subtree_before(&node_to_insert, insert_children);
|
||||||
|
|||||||
@ -37,10 +37,9 @@ impl<'a> TransactionBuilder<'a> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// // 0
|
/// // -- 0 (root)
|
||||||
/// // -- 0
|
/// // 0 -- text_1
|
||||||
/// // |-- text_1
|
/// // 1 -- text_2
|
||||||
/// // |-- text_2
|
|
||||||
/// use lib_ot::core::{DocumentTree, NodeSubTree, TransactionBuilder};
|
/// use lib_ot::core::{DocumentTree, NodeSubTree, TransactionBuilder};
|
||||||
/// let mut document = DocumentTree::new();
|
/// let mut document = DocumentTree::new();
|
||||||
/// let transaction = {
|
/// let transaction = {
|
||||||
@ -90,7 +89,7 @@ impl<'a> TransactionBuilder<'a> {
|
|||||||
pub fn update_attributes_at_path(&mut self, path: &Path, attributes: HashMap<String, Option<String>>) {
|
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 mut old_attributes: HashMap<String, Option<String>> = HashMap::new();
|
||||||
let node = self.document.node_at_path(path).unwrap();
|
let node = self.document.node_at_path(path).unwrap();
|
||||||
let node_data = self.document.arena.get(node).unwrap().get();
|
let node_data = self.document.get_node_data(node).unwrap();
|
||||||
|
|
||||||
for key in attributes.keys() {
|
for key in attributes.keys() {
|
||||||
let old_attrs = &node_data.attributes;
|
let old_attrs = &node_data.attributes;
|
||||||
@ -117,7 +116,7 @@ impl<'a> TransactionBuilder<'a> {
|
|||||||
let mut deleted_nodes = vec![];
|
let mut deleted_nodes = vec![];
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
deleted_nodes.push(self.get_deleted_nodes(node));
|
deleted_nodes.push(self.get_deleted_nodes(node));
|
||||||
node = node.following_siblings(&self.document.arena).next().unwrap();
|
node = self.document.following_siblings(node).next().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.operations.push(DocumentOperation::Delete {
|
self.operations.push(DocumentOperation::Delete {
|
||||||
@ -127,10 +126,10 @@ impl<'a> TransactionBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_deleted_nodes(&self, node_id: NodeId) -> NodeSubTree {
|
fn get_deleted_nodes(&self, node_id: NodeId) -> NodeSubTree {
|
||||||
let node_data = self.document.arena.get(node_id).unwrap().get();
|
let node_data = self.document.get_node_data(node_id).unwrap();
|
||||||
|
|
||||||
let mut children = vec![];
|
let mut children = vec![];
|
||||||
node_id.children(&self.document.arena).for_each(|child_id| {
|
self.document.children_from_node(node_id).for_each(|child_id| {
|
||||||
children.push(self.get_deleted_nodes(child_id));
|
children.push(self.get_deleted_nodes(child_id));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ fn test_documents() {
|
|||||||
|
|
||||||
assert!(document.node_at_path(0).is_some());
|
assert!(document.node_at_path(0).is_some());
|
||||||
let node = document.node_at_path(0).unwrap();
|
let node = document.node_at_path(0).unwrap();
|
||||||
let node_data = document.arena.get(node).unwrap().get();
|
let node_data = document.get_node_data(node).unwrap();
|
||||||
assert_eq!(node_data.node_type, "text");
|
assert_eq!(node_data.node_type, "text");
|
||||||
|
|
||||||
let transaction = {
|
let transaction = {
|
||||||
@ -81,22 +81,10 @@ fn test_inserts_subtrees() {
|
|||||||
document.apply(transaction).unwrap();
|
document.apply(transaction).unwrap();
|
||||||
|
|
||||||
let node = document.node_at_path(&Path(vec![0, 0])).unwrap();
|
let node = document.node_at_path(&Path(vec![0, 0])).unwrap();
|
||||||
let data = document.arena.get(node).unwrap().get();
|
let data = document.get_node_data(node).unwrap();
|
||||||
assert_eq!(data.node_type, "image");
|
assert_eq!(data.node_type, "image");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_insert_node() {
|
|
||||||
let node = NodeSubTree::new("text");
|
|
||||||
let root_path: Path = vec![0].into();
|
|
||||||
let op = DocumentOperation::Insert {path: root_path.clone(),nodes: vec![node.clone()] };
|
|
||||||
let mut document = DocumentTree::new();
|
|
||||||
document.apply_op(&op).unwrap();
|
|
||||||
let node_id = document.node_at_path(&root_path).unwrap();
|
|
||||||
|
|
||||||
assert!(document.child_at_index_of_path(node_id, 0).is_some());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_update_nodes() {
|
fn test_update_nodes() {
|
||||||
let mut document = DocumentTree::new();
|
let mut document = DocumentTree::new();
|
||||||
@ -117,7 +105,7 @@ fn test_update_nodes() {
|
|||||||
document.apply(transaction).unwrap();
|
document.apply(transaction).unwrap();
|
||||||
|
|
||||||
let node = document.node_at_path(&Path(vec![1])).unwrap();
|
let node = document.node_at_path(&Path(vec![1])).unwrap();
|
||||||
let node_data = document.arena.get(node).unwrap().get();
|
let node_data = document.get_node_data(node).unwrap();
|
||||||
let is_bold = node_data.attributes.0.get("bolded").unwrap().clone();
|
let is_bold = node_data.attributes.0.get("bolded").unwrap().clone();
|
||||||
assert_eq!(is_bold.unwrap(), "true");
|
assert_eq!(is_bold.unwrap(), "true");
|
||||||
}
|
}
|
||||||
@ -141,7 +129,7 @@ fn test_delete_nodes() {
|
|||||||
};
|
};
|
||||||
document.apply(transaction).unwrap();
|
document.apply(transaction).unwrap();
|
||||||
|
|
||||||
let len = document.root.children(&document.arena).fold(0, |count, _| count + 1);
|
let len = document.number_of_children();
|
||||||
assert_eq!(len, 2);
|
assert_eq!(len, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user