loro_ffi/container/tree.rs
1use std::sync::Arc;
2
3use loro::{ContainerTrait, LoroError, LoroResult, LoroTreeError, TreeID, ID};
4
5use crate::{ContainerID, DiffEvent, LoroDoc, LoroValue, Subscriber, Subscription};
6
7use super::LoroMap;
8
9pub enum TreeParentId {
10 Node { id: TreeID },
11 Root,
12 Deleted,
13 Unexist,
14}
15
16#[derive(Debug, Clone)]
17pub struct LoroTree {
18 pub(crate) inner: loro::LoroTree,
19}
20
21impl LoroTree {
22 pub fn new() -> Self {
23 Self {
24 inner: loro::LoroTree::new(),
25 }
26 }
27
28 /// Whether the container is attached to a document
29 ///
30 /// The edits on a detached container will not be persisted.
31 /// To attach the container to the document, please insert it into an attached container.
32 pub fn is_attached(&self) -> bool {
33 self.inner.is_attached()
34 }
35
36 /// If a detached container is attached, this method will return its corresponding attached handler.
37 pub fn get_attached(&self) -> Option<Arc<LoroTree>> {
38 self.inner
39 .get_attached()
40 .map(|x| Arc::new(LoroTree { inner: x }))
41 }
42
43 /// Create a new tree node and return the [`TreeID`].
44 ///
45 /// If the `parent` is `None`, the created node is the root of a tree.
46 /// Otherwise, the created node is a child of the parent tree node.
47 ///
48 /// # Example
49 ///
50 /// ```rust
51 /// use loro::LoroDoc;
52 ///
53 /// let doc = LoroDoc::new();
54 /// let tree = doc.get_tree("tree");
55 /// // create a root
56 /// let root = tree.create(None).unwrap();
57 /// // create a new child
58 /// let child = tree.create(root).unwrap();
59 /// ```
60 pub fn create(&self, parent: TreeParentId) -> LoroResult<TreeID> {
61 self.inner.create(parent)
62 }
63
64 /// Create a new tree node at the given index and return the [`TreeID`].
65 ///
66 /// If the `parent` is `None`, the created node is the root of a tree.
67 /// If the `index` is greater than the number of children of the parent, error will be returned.
68 pub fn create_at(&self, parent: TreeParentId, index: u32) -> LoroResult<TreeID> {
69 self.inner.create_at(parent, index as usize)
70 }
71
72 pub fn roots(&self) -> Vec<TreeID> {
73 self.inner.roots()
74 }
75
76 /// Move the `target` node to be a child of the `parent` node.
77 ///
78 /// If the `parent` is `None`, the `target` node will be a root.
79 ///
80 /// # Example
81 ///
82 /// ```rust
83 /// use loro::LoroDoc;
84 ///
85 /// let doc = LoroDoc::new();
86 /// let tree = doc.get_tree("tree");
87 /// let root = tree.create(None).unwrap();
88 /// let root2 = tree.create(None).unwrap();
89 /// // move `root2` to be a child of `root`.
90 /// tree.mov(root2, root).unwrap();
91 /// ```
92 pub fn mov(&self, target: TreeID, parent: TreeParentId) -> LoroResult<()> {
93 self.inner.mov(target, parent)
94 }
95
96 /// Move the `target` node to be a child of the `parent` node at the given index.
97 /// If the `parent` is `None`, the `target` node will be a root.
98 pub fn mov_to(&self, target: TreeID, parent: TreeParentId, to: u32) -> LoroResult<()> {
99 self.inner.mov_to(target, parent, to as usize)
100 }
101
102 /// Move the `target` node to be a child after the `after` node with the same parent.
103 pub fn mov_after(&self, target: TreeID, after: TreeID) -> LoroResult<()> {
104 self.inner.mov_after(target, after)
105 }
106
107 /// Move the `target` node to be a child before the `before` node with the same parent.
108 pub fn mov_before(&self, target: TreeID, before: TreeID) -> LoroResult<()> {
109 self.inner.mov_before(target, before)
110 }
111
112 /// Delete a tree node.
113 ///
114 /// Note: If the deleted node has children, the children do not appear in the state
115 /// rather than actually being deleted.
116 ///
117 /// # Example
118 ///
119 /// ```rust
120 /// use loro::LoroDoc;
121 ///
122 /// let doc = LoroDoc::new();
123 /// let tree = doc.get_tree("tree");
124 /// let root = tree.create(None).unwrap();
125 /// tree.delete(root).unwrap();
126 /// ```
127 pub fn delete(&self, target: TreeID) -> LoroResult<()> {
128 self.inner.delete(target)
129 }
130
131 /// Get the associated metadata map handler of a tree node.
132 ///
133 /// # Example
134 /// ```rust
135 /// use loro::LoroDoc;
136 ///
137 /// let doc = LoroDoc::new();
138 /// let tree = doc.get_tree("tree");
139 /// let root = tree.create(None).unwrap();
140 /// let root_meta = tree.get_meta(root).unwrap();
141 /// root_meta.insert("color", "red");
142 /// ```
143 pub fn get_meta(&self, target: TreeID) -> LoroResult<Arc<LoroMap>> {
144 self.inner
145 .get_meta(target)
146 .map(|h| Arc::new(LoroMap { inner: h }))
147 }
148
149 /// Return the parent of target node.
150 ///
151 /// - If the target node does not exist, throws Error.
152 /// - If the target node is a root node, return `None`.
153 pub fn parent(&self, target: TreeID) -> LoroResult<TreeParentId> {
154 if let Some(p) = self.inner.parent(target) {
155 Ok(p.into())
156 } else {
157 Err(LoroError::TreeError(LoroTreeError::TreeNodeNotExist(
158 target,
159 )))
160 }
161 }
162
163 /// Return whether target node exists.
164 pub fn contains(&self, target: TreeID) -> bool {
165 self.inner.contains(target)
166 }
167
168 /// Return whether target node is deleted.
169 ///
170 /// # Errors
171 ///
172 /// - If the target node does not exist, return `LoroTreeError::TreeNodeNotExist`.
173 pub fn is_node_deleted(&self, target: TreeID) -> LoroResult<bool> {
174 self.inner.is_node_deleted(&target)
175 }
176
177 /// Return all nodes, including deleted nodes
178 pub fn nodes(&self) -> Vec<TreeID> {
179 self.inner.nodes()
180 }
181
182 /// Return all children of the target node.
183 ///
184 /// If the parent node does not exist, return `None`.
185 pub fn children(&self, parent: TreeParentId) -> Option<Vec<TreeID>> {
186 self.inner.children(parent)
187 }
188
189 /// Return the number of children of the target node.
190 pub fn children_num(&self, parent: TreeParentId) -> Option<u32> {
191 self.inner.children_num(parent).map(|v| v as u32)
192 }
193
194 /// Return container id of the tree.
195 pub fn id(&self) -> ContainerID {
196 self.inner.id().into()
197 }
198
199 /// Return the fractional index of the target node with hex format.
200 pub fn fractional_index(&self, target: TreeID) -> Option<String> {
201 self.inner.fractional_index(target)
202 }
203
204 /// Return the flat array of the forest.
205 ///
206 /// Note: the metadata will be not resolved. So if you don't only care about hierarchy
207 /// but also the metadata, you should use [TreeHandler::get_value_with_meta()].
208 pub fn get_value(&self) -> LoroValue {
209 self.inner.get_value().into()
210 }
211
212 /// Return the flat array of the forest, each node is with metadata.
213 pub fn get_value_with_meta(&self) -> LoroValue {
214 self.inner.get_value_with_meta().into()
215 }
216
217 /// Whether the fractional index is enabled.
218 pub fn is_fractional_index_enabled(&self) -> bool {
219 self.inner.is_fractional_index_enabled()
220 }
221
222 /// Enable fractional index for Tree Position.
223 ///
224 /// The jitter is used to avoid conflicts when multiple users are creating the node at the same position.
225 /// value 0 is default, which means no jitter, any value larger than 0 will enable jitter.
226 ///
227 /// Generally speaking, jitter will affect the growth rate of document size.
228 /// [Read more about it](https://www.loro.dev/blog/movable-tree#implementation-and-encoding-size)
229 #[inline]
230 pub fn enable_fractional_index(&self, jitter: u8) {
231 self.inner.enable_fractional_index(jitter);
232 }
233
234 /// Disable the fractional index generation for Tree Position when
235 /// you don't need the Tree's siblings to be sorted. The fractional index will be always default.
236 #[inline]
237 pub fn disable_fractional_index(&self) {
238 self.inner.disable_fractional_index();
239 }
240
241 pub fn is_deleted(&self) -> bool {
242 self.inner.is_deleted()
243 }
244
245 pub fn get_last_move_id(&self, target: &TreeID) -> Option<ID> {
246 self.inner.get_last_move_id(target)
247 }
248
249 pub fn doc(&self) -> Option<Arc<LoroDoc>> {
250 self.inner.doc().map(|x| Arc::new(LoroDoc { doc: x }))
251 }
252
253 pub fn subscribe(&self, subscriber: Arc<dyn Subscriber>) -> Option<Arc<Subscription>> {
254 self.inner
255 .subscribe(Arc::new(move |e| {
256 subscriber.on_diff(DiffEvent::from(e));
257 }))
258 .map(|x| Arc::new(x.into()))
259 }
260}
261
262impl Default for LoroTree {
263 fn default() -> Self {
264 Self::new()
265 }
266}
267
268impl From<loro::TreeParentId> for TreeParentId {
269 fn from(value: loro::TreeParentId) -> Self {
270 match value {
271 loro::TreeParentId::Node(id) => TreeParentId::Node { id },
272 loro::TreeParentId::Root => TreeParentId::Root,
273 loro::TreeParentId::Deleted => TreeParentId::Deleted,
274 loro::TreeParentId::Unexist => TreeParentId::Unexist,
275 }
276 }
277}
278
279impl From<TreeParentId> for loro::TreeParentId {
280 fn from(value: TreeParentId) -> Self {
281 match value {
282 TreeParentId::Node { id } => loro::TreeParentId::Node(id),
283 TreeParentId::Root => loro::TreeParentId::Root,
284 TreeParentId::Deleted => loro::TreeParentId::Deleted,
285 TreeParentId::Unexist => loro::TreeParentId::Unexist,
286 }
287 }
288}