diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index da8bc0ff1c..596f1fe694 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -741,6 +741,12 @@ dependencies = [ "serde", ] +[[package]] +name = "indextree" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42b4b46b3311ebd8e5cd44f6b03b36e0f48a70552cf6b036afcebc5626794066" + [[package]] name = "instant" version = "0.1.12" @@ -809,6 +815,7 @@ dependencies = [ "bytes", "dashmap", "derive_more", + "indextree", "lazy_static", "log", "md5", diff --git a/shared-lib/lib-ot/Cargo.toml b/shared-lib/lib-ot/Cargo.toml index a1a577132e..d47968dcfe 100644 --- a/shared-lib/lib-ot/Cargo.toml +++ b/shared-lib/lib-ot/Cargo.toml @@ -24,6 +24,7 @@ lazy_static = "1.4.0" strum = "0.21" strum_macros = "0.21" bytes = "1.0" +indextree = "4.4.0" [features] diff --git a/shared-lib/lib-ot/src/core/document/attributes.rs b/shared-lib/lib-ot/src/core/document/attributes.rs new file mode 100644 index 0000000000..ae9d1fbffb --- /dev/null +++ b/shared-lib/lib-ot/src/core/document/attributes.rs @@ -0,0 +1,9 @@ +use std::collections::HashMap; + +pub struct NodeAttributes(HashMap>); + +impl NodeAttributes { + pub fn new() -> NodeAttributes { + NodeAttributes(HashMap::new()) + } +} diff --git a/shared-lib/lib-ot/src/core/document/document.rs b/shared-lib/lib-ot/src/core/document/document.rs new file mode 100644 index 0000000000..fa8e2aea6a --- /dev/null +++ b/shared-lib/lib-ot/src/core/document/document.rs @@ -0,0 +1,52 @@ +use crate::core::document::position::Position; +use crate::core::NodeData; +use indextree::{Arena, NodeId}; + +pub struct DocumentTree { + arena: Arena, + root: NodeId, +} + +impl DocumentTree { + pub fn new() -> DocumentTree { + let mut arena = Arena::new(); + let root = arena.new_node(NodeData::new("root".into())); + DocumentTree { + arena: Arena::new(), + root, + } + } + + pub fn node_at_path(&self, position: &Position) -> Option { + if position.is_empty() { + return None; + } + + let mut iterate_node = self.root; + + for id in &position.0 { + let child = self.child_at_index_of_path(iterate_node, id.clone()); + iterate_node = match child { + Some(node) => node, + None => return None, + }; + } + + Some(iterate_node) + } + + fn child_at_index_of_path(&self, at_node: NodeId, index: usize) -> Option { + let children = at_node.children(&self.arena); + + let mut counter = 0; + for child in children { + if counter == index { + return Some(child); + } + + counter += 1; + } + + None + } +} diff --git a/shared-lib/lib-ot/src/core/document/mod.rs b/shared-lib/lib-ot/src/core/document/mod.rs new file mode 100644 index 0000000000..efbf9f362c --- /dev/null +++ b/shared-lib/lib-ot/src/core/document/mod.rs @@ -0,0 +1,8 @@ +mod attributes; +mod document; +mod node; +mod position; + +pub use attributes::*; +pub use document::*; +pub use node::*; diff --git a/shared-lib/lib-ot/src/core/document/node.rs b/shared-lib/lib-ot/src/core/document/node.rs new file mode 100644 index 0000000000..7f0f172cd6 --- /dev/null +++ b/shared-lib/lib-ot/src/core/document/node.rs @@ -0,0 +1,15 @@ +use crate::core::NodeAttributes; + +pub struct NodeData { + pub node_type: String, + pub attributes: NodeAttributes, +} + +impl NodeData { + pub fn new(node_type: &str) -> NodeData { + NodeData { + node_type: node_type.into(), + attributes: NodeAttributes::new(), + } + } +} diff --git a/shared-lib/lib-ot/src/core/document/position.rs b/shared-lib/lib-ot/src/core/document/position.rs new file mode 100644 index 0000000000..6e1983b440 --- /dev/null +++ b/shared-lib/lib-ot/src/core/document/position.rs @@ -0,0 +1,7 @@ +pub struct Position(pub Vec); + +impl Position { + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} diff --git a/shared-lib/lib-ot/src/core/mod.rs b/shared-lib/lib-ot/src/core/mod.rs index 7c1ed3f2ef..262233c85a 100644 --- a/shared-lib/lib-ot/src/core/mod.rs +++ b/shared-lib/lib-ot/src/core/mod.rs @@ -1,9 +1,11 @@ mod delta; +mod document; mod interval; mod operation; mod ot_str; pub use delta::*; +pub use document::*; pub use interval::*; pub use operation::*; pub use ot_str::*; diff --git a/shared-lib/lib-ot/tests/main.rs b/shared-lib/lib-ot/tests/main.rs index 8b13789179..2c766017e4 100644 --- a/shared-lib/lib-ot/tests/main.rs +++ b/shared-lib/lib-ot/tests/main.rs @@ -1 +1,7 @@ +use lib_ot::core::DocumentTree; +#[test] +fn main() { + // Create a new arena + let _document = DocumentTree::new(); +}