1use crate::encoding::{self, TreeType};
4use serde::{Deserialize, Serialize};
5use std::{
6 cell::RefCell,
7 io::{self, Write},
8 path::PathBuf,
9 rc::{Rc, Weak},
10};
11use thiserror::Error;
12
13#[derive(Clone, Debug, Deserialize, Serialize)]
14#[serde(from = "encoding::Tree", into = "encoding::Tree")]
15pub struct Tree {
16 version: encoding::Version,
17 ty: TreeType,
18 node: Node,
19}
20
21impl From<encoding::Tree> for Tree {
22 fn from(value: encoding::Tree) -> Self {
23 Self::from_encoding(value)
24 }
25}
26
27impl From<Tree> for encoding::Tree {
28 fn from(value: Tree) -> Self {
29 value.into_encoding()
30 }
31}
32
33impl Tree {
34 pub fn new(name: impl AsRef<str>, icon: impl AsRef<str>) -> Self {
35 Self {
36 version: encoding::Version::current(),
37 ty: TreeType::Root,
38 node: Node::new(name, icon),
39 }
40 }
41
42 pub fn from_encoding(tree: encoding::Tree) -> Self {
43 Self {
44 version: tree.version,
45 ty: tree.ty,
46 node: Node::from_encoding(tree.node),
47 }
48 }
49
50 pub fn into_encoding(&self) -> encoding::Tree {
51 encoding::Tree {
52 version: self.version,
53 ty: self.ty,
54 node: self.node.into_encoding(),
55 }
56 }
57
58 pub fn root(&self) -> Node {
60 self.node.clone()
61 }
62
63 pub fn get_node_by_line(&self, line: usize) -> Option<Node> {
67 let (_, node) = self.node.get_node_by_line(line);
68 node
69 }
70
71 pub fn get_node_by_path<'a>(
73 &self,
74 path: impl IntoIterator<Item = &'a str>,
75 auto_create_nodes: bool,
76 ) -> Option<Node> {
77 self
78 .node
79 .get_node_by_path(path.into_iter(), auto_create_nodes)
80 }
81}
82
83#[derive(Clone, Debug)]
87pub struct WeakNode {
88 inner: Weak<RefCell<NodeInner>>,
89}
90
91impl WeakNode {
92 fn upgrade(&self) -> Option<Node> {
93 self.inner.upgrade().map(|inner| Node { inner })
94 }
95}
96
97#[derive(Clone, Debug, Deserialize, Serialize)]
98#[serde(from = "encoding::Node", into = "encoding::Node")]
99pub struct Node {
100 inner: Rc<RefCell<NodeInner>>,
101}
102
103impl PartialEq for Node {
104 fn eq(&self, other: &Self) -> bool {
105 self.inner.as_ptr().eq(&other.inner.as_ptr())
106 }
107}
108
109impl From<encoding::Node> for Node {
110 fn from(value: encoding::Node) -> Self {
111 Self::from_encoding(value)
112 }
113}
114
115impl From<Node> for encoding::Node {
116 fn from(value: Node) -> Self {
117 value.into_encoding()
118 }
119}
120
121impl Node {
122 pub fn new(name: impl AsRef<str>, icon: impl AsRef<str>) -> Self {
123 Self::new_raw(name.as_ref(), icon.as_ref(), false, None)
124 }
125
126 fn new_raw(name: &str, icon: &str, is_expanded: bool, parent: Option<WeakNode>) -> Self {
127 let name = name.trim().to_owned();
128
129 let icon = icon.trim_start().to_owned();
131
132 Self {
133 inner: Rc::new(RefCell::new(NodeInner {
134 name,
135 icon,
136 is_expanded,
137 parent,
138 data: None,
139 children: Vec::new(),
140 })),
141 }
142 }
143
144 fn downgrade(&self) -> WeakNode {
145 WeakNode {
146 inner: Rc::downgrade(&self.inner),
147 }
148 }
149
150 pub fn from_encoding(node: encoding::Node) -> Self {
151 Self::from_encoding_rec(None, node)
152 }
153
154 fn from_encoding_rec(parent: Option<WeakNode>, mut node: encoding::Node) -> Self {
155 let current = Self::new_raw(
156 &node
157 .contents
158 .pop()
159 .map(|text| text.text)
160 .unwrap_or_default(),
161 &node.icon,
162 node.is_expanded,
163 parent,
164 );
165
166 let children = node
167 .children
168 .into_iter()
169 .map(|node| Self::from_encoding_rec(Some(current.downgrade()), node))
170 .collect();
171
172 let data = node
173 .data
174 .map(NodeData::file)
175 .or_else(move || node.url.map(NodeData::link));
176
177 {
178 let mut inner = current.inner.borrow_mut();
179 inner.children = children;
180 inner.data = data;
181 }
182
183 current
184 }
185
186 pub fn into_encoding(&self) -> encoding::Node {
187 let node = self.inner.borrow();
188 let data;
189 let url;
190
191 match node.data {
192 Some(NodeData::File(ref path)) => {
193 data = Some(path.clone());
194 url = None;
195 }
196
197 Some(NodeData::Link(ref link)) => {
198 url = Some(link.clone());
199 data = None;
200 }
201
202 None => {
203 data = None;
204 url = None;
205 }
206 }
207
208 encoding::Node {
209 icon: node.icon.clone(),
210 is_expanded: node.is_expanded,
211 contents: vec![encoding::Text {
212 text: node.name.clone(),
213 }],
214 data,
215 url,
216 children: node.children.iter().map(Self::into_encoding).collect(),
217 }
218 }
219
220 fn get_node_by_line(&self, mut line: usize) -> (usize, Option<Self>) {
221 let node = self.inner.borrow();
222
223 if line == 0 {
224 return (0, Some(self.clone()));
225 }
226
227 line -= 1;
229
230 if !node.is_expanded || node.children.is_empty() {
231 return (line, None);
232 }
233
234 for child in &node.children {
235 let (new_line, node) = child.get_node_by_line(line);
236 if node.is_some() {
237 return (new_line, node);
238 }
239
240 line = new_line;
241 }
242
243 (line, None)
244 }
245
246 fn get_node_by_path<'a>(
247 &self,
248 mut path: impl Iterator<Item = &'a str>,
249 auto_create_nodes: bool,
250 ) -> Option<Self> {
251 let node = self.inner.borrow();
252
253 match path.next() {
254 None => Some(self.clone()),
255
256 Some(node_name) => {
257 match node
260 .children
261 .iter()
262 .find(|node| node.inner.borrow().name == node_name)
263 {
264 Some(child) => child.get_node_by_path(path, auto_create_nodes),
265 None => {
266 drop(node);
267
268 if auto_create_nodes {
269 let child = Node::new(node_name, "");
270 self.insert_bottom(child.clone());
271 child.get_node_by_path(path, auto_create_nodes)
272 } else {
273 None
274 }
275 }
276 }
277 }
278 }
279 }
280
281 fn get_index(&self, parent: &Node) -> Result<usize, NodeError> {
285 for (i, child) in parent.inner.borrow().children.iter().enumerate() {
286 if self == child {
287 return Ok(i);
288 }
289 }
290
291 Err(NodeError::NotContainedInParent)
292 }
293
294 #[cfg(test)]
295 fn get_index_from_parent(&self) -> Result<usize, NodeError> {
296 self.parent().and_then(|parent| self.get_index(&parent))
297 }
298
299 pub fn name(&self) -> String {
300 self.inner.borrow().name.to_owned()
301 }
302
303 pub fn set_name(&self, name: impl AsRef<str>) -> Result<(), NodeError> {
304 let name = name.as_ref().trim().to_owned();
305
306 if name.is_empty() {
307 return Err(NodeError::EmptyName);
308 }
309
310 self.inner.borrow_mut().name = name;
311 Ok(())
312 }
313
314 pub fn icon(&self) -> String {
315 self.inner.borrow().icon.to_owned()
316 }
317
318 pub fn set_icon(&self, icon: impl AsRef<str>) {
319 let icon = icon.as_ref().trim().to_owned();
320 self.inner.borrow_mut().icon = icon;
321 }
322
323 pub fn data(&self) -> Option<NodeData> {
324 self.inner.borrow().data.clone()
325 }
326
327 pub fn set_data(&self, data: NodeData) -> Result<(), NodeError> {
328 let current = self.inner.borrow();
329
330 match (current.data.as_ref(), &data) {
331 (None, NodeData::Link(link)) => {
333 if link.is_empty() {
334 return Err(NodeError::NoData);
335 }
336
337 drop(current);
338 self.inner.borrow_mut().data = Some(data);
339 }
340
341 (None, NodeData::File(path)) => {
342 if path.as_os_str().is_empty() {
343 return Err(NodeError::NoData);
344 }
345
346 drop(current);
347 self.inner.borrow_mut().data = Some(data);
348 }
349
350 (Some(NodeData::Link(_)), NodeData::Link(_)) => {
351 drop(current);
352 self.inner.borrow_mut().data = Some(data)
353 }
354
355 (Some(NodeData::File(_)), NodeData::File(_)) => return Err(NodeError::FileDataAlreadyExists),
356
357 _ => return Err(NodeError::MismatchDataType),
359 }
360
361 Ok(())
362 }
363
364 pub fn is_expanded(&self) -> bool {
365 self.inner.borrow().is_expanded
366 }
367
368 pub fn set_expanded(&self, is_expanded: bool) {
369 self.inner.borrow_mut().is_expanded = is_expanded;
370 }
371
372 pub fn parent(&self) -> Result<Node, NodeError> {
373 self
374 .inner
375 .borrow()
376 .parent
377 .as_ref()
378 .and_then(WeakNode::upgrade)
379 .ok_or(NodeError::NoParent)
380 }
381
382 pub fn insert_top(&self, node: Node) {
383 node.inner.borrow_mut().parent = Some(self.downgrade());
384 self.inner.borrow_mut().children.insert(0, node);
385 }
386
387 pub fn insert_bottom(&self, node: Node) {
388 node.inner.borrow_mut().parent = Some(self.downgrade());
389 self.inner.borrow_mut().children.push(node);
390 }
391
392 pub fn insert_before(&self, node: Node) -> Result<(), NodeError> {
393 let parent = self.parent()?;
394 let i = self.get_index(&parent)?;
395
396 node.inner.borrow_mut().parent = Some(parent.downgrade());
397 parent.inner.borrow_mut().children.insert(i, node);
398 Ok(())
399 }
400
401 pub fn insert_after(&self, node: Node) -> Result<(), NodeError> {
402 let parent = self.parent()?;
403 let i = self.get_index(&parent)? + 1;
404
405 node.inner.borrow_mut().parent = Some(parent.downgrade());
406 parent.inner.borrow_mut().children.insert(i, node);
407 Ok(())
408 }
409
410 pub fn delete(&self, node: Node) -> Result<(), NodeError> {
411 let mut inner = self.inner.borrow_mut();
412 let i = inner
413 .children
414 .iter()
415 .enumerate()
416 .find_map(|(i, n)| if n == &node { Some(i) } else { None })
417 .ok_or(NodeError::NotContainedInParent)?;
418
419 let _ = inner.children.remove(i);
420 Ok(())
421 }
422
423 pub fn move_top(&self, node: Node) -> Result<(), NodeError> {
424 let parent = node.parent()?;
425
426 parent.delete(node.clone())?;
427 self.insert_top(node);
428 Ok(())
429 }
430
431 pub fn move_bottom(&self, node: Node) -> Result<(), NodeError> {
432 let parent = node.parent()?;
433
434 parent.delete(node.clone())?;
435 self.insert_bottom(node);
436 Ok(())
437 }
438
439 pub fn move_before(&self, node: Node) -> Result<(), NodeError> {
440 let parent = node.parent()?;
441
442 parent.delete(node.clone())?;
443 self.insert_before(node)?;
444 Ok(())
445 }
446
447 pub fn move_after(&self, node: Node) -> Result<(), NodeError> {
448 let parent = node.parent()?;
449
450 parent.delete(node.clone())?;
451 self.insert_after(node)?;
452 Ok(())
453 }
454
455 pub fn toggle_expand(&self) {
456 let mut node = self.inner.borrow_mut();
457 node.is_expanded = !node.is_expanded;
458 }
459
460 pub fn paths(&self, prefix: impl AsRef<str>, filter: NodeFilter) -> Vec<String> {
461 let prefix = prefix.as_ref();
462 let mut all_paths = Vec::new();
463
464 if filter.accepts(self) {
465 all_paths.push(prefix.to_owned());
466 }
467
468 let prefix = if prefix == "/" { "" } else { prefix };
469 self.paths_rec(prefix, &mut all_paths, filter);
470 all_paths
471 }
472
473 fn paths_rec(&self, parent: &str, paths: &mut Vec<String>, filter: NodeFilter) {
474 for child in &self.inner.borrow().children {
475 let path = format!("{parent}/{name}", name = child.name());
476
477 if filter.accepts(child) {
478 paths.push(path.clone());
479 }
480
481 child.paths_rec(&path, paths, filter);
482 }
483 }
484
485 pub fn write_paths(
487 &self,
488 prefix: &str,
489 filter: NodeFilter,
490 writer: &mut impl Write,
491 ) -> Result<(), NodeError> {
492 for path in self.paths(prefix, filter) {
493 writeln!(writer, "{}", path).map_err(NodeError::CannotWritePaths)?;
494 }
495
496 Ok(())
497 }
498}
499
500#[derive(Clone, Debug)]
501pub struct NodeInner {
502 name: String,
503 icon: String,
504 is_expanded: bool,
505 parent: Option<WeakNode>,
506 data: Option<NodeData>,
507 children: Vec<Node>,
508}
509
510#[derive(Clone, Debug, Eq, PartialEq)]
511pub enum NodeData {
512 File(PathBuf),
513 Link(String),
514}
515
516impl NodeData {
517 pub fn file(path: impl Into<PathBuf>) -> Self {
518 NodeData::File(path.into())
519 }
520
521 pub fn link(link: impl Into<String>) -> Self {
522 NodeData::Link(link.into())
523 }
524}
525
526#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
527pub enum NodeFilter {
528 #[default]
529 Always,
530 FileOrLink,
531 FileOnly,
532 LinkOnly,
533}
534
535impl NodeFilter {
536 pub fn new(file: bool, uri: bool) -> Self {
537 match (file, uri) {
538 (true, true) => Self::FileOrLink,
539 (true, false) => Self::FileOnly,
540 (false, true) => Self::LinkOnly,
541 (false, false) => Self::Always,
542 }
543 }
544
545 fn accepts(&self, node: &Node) -> bool {
546 match self {
547 NodeFilter::Always => true,
548 NodeFilter::FileOrLink => node.inner.borrow().data.is_some(),
549 NodeFilter::FileOnly => matches!(node.inner.borrow().data, Some(NodeData::File(..))),
550 NodeFilter::LinkOnly => matches!(node.inner.borrow().data, Some(NodeData::Link(..))),
551 }
552 }
553}
554
555#[derive(Debug, Error)]
556pub enum NodeError {
557 #[error("cannot insert; no parent")]
558 NoParent,
559
560 #[error("the node is not contained in its supposed parent")]
561 NotContainedInParent,
562
563 #[error("cannot set name; name cannot be empty")]
564 EmptyName,
565
566 #[error("cannot set data; file data already exists")]
567 FileDataAlreadyExists,
568
569 #[error("cannot set data; already exists with a different type")]
570 MismatchDataType,
571
572 #[error("no data")]
573 NoData,
574
575 #[error("cannot create associated data file: {0}")]
576 CannotCreateDataFile(io::Error),
577
578 #[error("cannot write paths")]
579 CannotWritePaths(io::Error),
580}
581
582pub fn path_iter(path: &str) -> impl Iterator<Item = &str> {
586 path.split('/').filter(|frag| !frag.trim().is_empty())
587}
588
589#[cfg(test)]
590mod tests {
591 use crate::{
592 encoding::{self, TreeType, Version},
593 node::{Node, NodeData, NodeError, NodeFilter, Tree},
594 };
595
596 use super::path_iter;
597
598 #[test]
599 fn path_iter_test() {
600 assert_eq!(path_iter("").collect::<Vec<_>>(), Vec::<&str>::new());
601 assert_eq!(path_iter("/").collect::<Vec<_>>(), Vec::<&str>::new());
602 assert_eq!(path_iter("//").collect::<Vec<_>>(), Vec::<&str>::new());
603 assert_eq!(
604 path_iter("/Foo/Bar/Zoo").collect::<Vec<_>>(),
605 vec!["Foo", "Bar", "Zoo"]
606 );
607
608 assert_eq!(path_iter("/A B").collect::<Vec<_>>(), vec!["A B"]);
609 }
610
611 #[test]
612 fn get_node_by_line_no_child() {
613 let tree = Tree::from_encoding(encoding::Tree {
614 version: Version::default(),
615 ty: TreeType::Root,
616 node: encoding::Node::new_by_expand_state("root", false, vec![]),
617 });
618
619 assert_eq!(
620 tree
621 .get_node_by_line(0)
622 .as_ref()
623 .map(|node| node.inner.borrow())
624 .as_ref()
625 .map(|node| node.name.as_str()),
626 Some("root")
627 );
628 assert_eq!(tree.get_node_by_line(1), None);
629 assert_eq!(tree.get_node_by_line(2), None);
630
631 let tree = Tree::from_encoding(encoding::Tree {
632 version: Version::default(),
633 ty: TreeType::Root,
634 node: encoding::Node::new_by_expand_state("root", true, vec![]),
635 });
636
637 assert_eq!(
638 tree
639 .get_node_by_line(0)
640 .as_ref()
641 .map(|node| node.inner.borrow())
642 .as_ref()
643 .map(|node| node.name.as_str()),
644 Some("root")
645 );
646 assert_eq!(
647 tree
648 .get_node_by_line(0)
649 .as_ref()
650 .map(|node| node.inner.borrow())
651 .as_ref()
652 .map(|node| node.name.as_str()),
653 Some("root")
654 );
655 assert_eq!(tree.get_node_by_line(1), None);
656 assert_eq!(tree.get_node_by_line(2), None);
657 }
658
659 #[test]
669 fn get_node_by_line_with_children() {
670 let tree = Tree::from_encoding(encoding::Tree {
671 version: Version::default(),
672 ty: TreeType::Root,
673 node: encoding::Node::new_by_expand_state(
674 "root",
675 true,
676 vec![
677 encoding::Node::new_by_expand_state(
678 "a",
679 false,
680 vec![
681 encoding::Node::new_by_expand_state("x", false, vec![]),
682 encoding::Node::new_by_expand_state("y", false, vec![]),
683 ],
684 ),
685 encoding::Node::new_by_expand_state(
686 "b",
687 true,
688 vec![encoding::Node::new_by_expand_state("z", false, vec![])],
689 ),
690 encoding::Node::new_by_expand_state("c", false, vec![]),
691 ],
692 ),
693 });
694
695 assert_eq!(
696 tree
697 .get_node_by_line(0)
698 .as_ref()
699 .map(|node| node.inner.borrow())
700 .as_ref()
701 .map(|node| node.name.as_str()),
702 Some("root")
703 );
704 assert_eq!(
705 tree
706 .get_node_by_line(1)
707 .as_ref()
708 .map(|node| node.inner.borrow())
709 .as_ref()
710 .map(|node| node.name.as_str()),
711 Some("a")
712 );
713 assert_eq!(
714 tree
715 .get_node_by_line(2)
716 .as_ref()
717 .map(|node| node.inner.borrow())
718 .as_ref()
719 .map(|node| node.name.as_str()),
720 Some("b")
721 );
722 assert_eq!(
723 tree
724 .get_node_by_line(3)
725 .as_ref()
726 .map(|node| node.inner.borrow())
727 .as_ref()
728 .map(|node| node.name.as_str()),
729 Some("z")
730 );
731 assert_eq!(
732 tree
733 .get_node_by_line(4)
734 .as_ref()
735 .map(|node| node.inner.borrow())
736 .as_ref()
737 .map(|node| node.name.as_str()),
738 Some("c")
739 );
740 }
741
742 #[test]
743 fn get_node_by_path_no_child() {
744 let tree = Tree::from_encoding(encoding::Tree {
745 version: Version::default(),
746 ty: TreeType::Root,
747 node: encoding::Node::new_by_expand_state("root", false, vec![]),
748 });
749
750 assert_eq!(
751 tree
752 .get_node_by_line(0)
753 .as_ref()
754 .map(|node| node.inner.borrow())
755 .as_ref()
756 .map(|node| node.name.as_str()),
757 Some("root")
758 );
759 assert_eq!(tree.get_node_by_path(["test"], false), None);
760
761 let tree = Tree::from_encoding(encoding::Tree {
762 version: Version::default(),
763 ty: TreeType::Root,
764 node: encoding::Node::new_by_expand_state("root", true, vec![]),
765 });
766
767 assert_eq!(
768 tree
769 .get_node_by_line(0)
770 .as_ref()
771 .map(|node| node.inner.borrow())
772 .as_ref()
773 .map(|node| node.name.as_str()),
774 Some("root")
775 );
776 assert_eq!(tree.get_node_by_path(["test"], false), None);
777 }
778
779 #[test]
789 fn get_node_by_path_with_children() {
790 let tree = Tree::from_encoding(encoding::Tree {
791 version: Version::default(),
792 ty: TreeType::Root,
793 node: encoding::Node::new_by_expand_state(
794 "root",
795 true,
796 vec![
797 encoding::Node::new_by_expand_state(
798 "a",
799 false,
800 vec![
801 encoding::Node::new_by_expand_state("x", false, vec![]),
802 encoding::Node::new_by_expand_state("y", false, vec![]),
803 ],
804 ),
805 encoding::Node::new_by_expand_state(
806 "b",
807 true,
808 vec![encoding::Node::new_by_expand_state("z", false, vec![])],
809 ),
810 encoding::Node::new_by_expand_state("c", false, vec![]),
811 ],
812 ),
813 });
814
815 assert_eq!(
816 tree
817 .get_node_by_line(0)
818 .as_ref()
819 .map(|node| node.inner.borrow())
820 .as_ref()
821 .map(|node| node.name.as_str()),
822 Some("root")
823 );
824 assert_eq!(
825 tree
826 .get_node_by_path(["a"], false)
827 .as_ref()
828 .map(|node| node.inner.borrow())
829 .as_ref()
830 .map(|node| node.name.as_str()),
831 Some("a")
832 );
833 assert_eq!(
834 tree
835 .get_node_by_path(["a", "x"], false)
836 .as_ref()
837 .map(|node| node.inner.borrow())
838 .as_ref()
839 .map(|node| node.name.as_str()),
840 Some("x")
841 );
842 assert_eq!(
843 tree
844 .get_node_by_path(["a", "y"], false)
845 .as_ref()
846 .map(|node| node.inner.borrow())
847 .as_ref()
848 .map(|node| node.name.as_str()),
849 Some("y")
850 );
851 assert_eq!(
852 tree
853 .get_node_by_path(["b"], false)
854 .as_ref()
855 .map(|node| node.inner.borrow())
856 .as_ref()
857 .map(|node| node.name.as_str()),
858 Some("b")
859 );
860 assert_eq!(
861 tree
862 .get_node_by_path(["b", "z"], false)
863 .as_ref()
864 .map(|node| node.inner.borrow())
865 .as_ref()
866 .map(|node| node.name.as_str()),
867 Some("z")
868 );
869 assert_eq!(
870 tree
871 .get_node_by_path(["c"], false)
872 .as_ref()
873 .map(|node| node.inner.borrow())
874 .as_ref()
875 .map(|node| node.name.as_str()),
876 Some("c")
877 );
878 }
879
880 #[test]
881 fn get_index_from_parent() {
882 let tree = Tree::from_encoding(encoding::Tree {
883 version: Version::default(),
884 ty: TreeType::Root,
885 node: encoding::Node::new_by_expand_state(
886 "root",
887 true,
888 vec![
889 encoding::Node::new_by_expand_state(
890 "a",
891 false,
892 vec![
893 encoding::Node::new_by_expand_state("x", false, vec![]),
894 encoding::Node::new_by_expand_state("y", false, vec![]),
895 ],
896 ),
897 encoding::Node::new_by_expand_state(
898 "b",
899 true,
900 vec![encoding::Node::new_by_expand_state("z", false, vec![])],
901 ),
902 encoding::Node::new_by_expand_state("c", false, vec![]),
903 ],
904 ),
905 });
906
907 assert!(matches!(
908 tree
909 .get_node_by_path(["a", "x"], false)
910 .unwrap()
911 .get_index_from_parent(),
912 Ok(0)
913 ));
914 assert!(matches!(
915 tree
916 .get_node_by_path(["a", "y"], false)
917 .unwrap()
918 .get_index_from_parent(),
919 Ok(1)
920 ));
921 }
922
923 #[test]
924 fn insert() {
925 let tree = Tree::new("root", "");
926 let node = tree.get_node_by_line(0).unwrap();
927
928 node.insert_bottom(Node::new("x", ""));
929 node.insert_bottom(Node::new("y", ""));
930 node.insert_bottom(Node::new("z", ""));
931 node.insert_top(Node::new("c", ""));
932 node.insert_top(Node::new("b", ""));
933 node.insert_top(Node::new("a", ""));
934
935 tree
936 .get_node_by_path(["c"], false)
937 .unwrap()
938 .insert_after(Node::new("d", ""))
939 .unwrap();
940
941 tree
942 .get_node_by_path(["x"], false)
943 .unwrap()
944 .insert_before(Node::new("w", ""))
945 .unwrap();
946
947 assert!(matches!(
948 tree
949 .get_node_by_path(["a"], false)
950 .unwrap()
951 .get_index_from_parent(),
952 Ok(0)
953 ));
954 assert!(matches!(
955 tree
956 .get_node_by_path(["b"], false)
957 .unwrap()
958 .get_index_from_parent(),
959 Ok(1)
960 ));
961 assert!(matches!(
962 tree
963 .get_node_by_path(["c"], false)
964 .unwrap()
965 .get_index_from_parent(),
966 Ok(2)
967 ));
968 assert!(matches!(
969 tree
970 .get_node_by_path(["d"], false)
971 .unwrap()
972 .get_index_from_parent(),
973 Ok(3)
974 ));
975 assert!(matches!(
976 tree
977 .get_node_by_path(["w"], false)
978 .unwrap()
979 .get_index_from_parent(),
980 Ok(4)
981 ));
982 assert!(matches!(
983 tree
984 .get_node_by_path(["x"], false)
985 .unwrap()
986 .get_index_from_parent(),
987 Ok(5)
988 ));
989 assert!(matches!(
990 tree
991 .get_node_by_path(["y"], false)
992 .unwrap()
993 .get_index_from_parent(),
994 Ok(6)
995 ));
996 assert!(matches!(
997 tree
998 .get_node_by_path(["z"], false)
999 .unwrap()
1000 .get_index_from_parent(),
1001 Ok(7)
1002 ));
1003 }
1004
1005 #[test]
1006 fn delete() {
1007 let tree = Tree::new("root", "");
1008 let node = tree.get_node_by_line(0).unwrap();
1009
1010 node.insert_bottom(Node::new("x", ""));
1011 node.insert_bottom(Node::new("y", ""));
1012
1013 let x = tree.get_node_by_path(["x"], false).unwrap();
1014 x.insert_bottom(Node::new("a", ""));
1015 x.insert_bottom(Node::new("b", ""));
1016 x.insert_bottom(Node::new("c", ""));
1017
1018 let b = tree.get_node_by_path(["x", "b"], false).unwrap();
1019 x.delete(b).unwrap();
1020
1021 assert_eq!(tree.get_node_by_path(["x", "b"], false), None);
1022 }
1023
1024 #[test]
1025 fn select_move() {
1026 let tree = Tree::new("root", "");
1027 let node = tree.get_node_by_line(0).unwrap();
1028
1029 node.insert_bottom(Node::new("x", ""));
1030 node.insert_bottom(Node::new("y", ""));
1031 node.insert_bottom(Node::new("z", ""));
1032 node.insert_top(Node::new("c", ""));
1033 node.insert_top(Node::new("b", ""));
1034 node.insert_top(Node::new("a", ""));
1035
1036 let a = tree.get_node_by_path(["a"], false).unwrap();
1037 let b = tree.get_node_by_path(["b"], false).unwrap();
1038 let c = tree.get_node_by_path(["c"], false).unwrap();
1039 let x = tree.get_node_by_path(["x"], false).unwrap();
1040 let y = tree.get_node_by_path(["y"], false).unwrap();
1041 let z = tree.get_node_by_path(["z"], false).unwrap();
1042
1043 a.move_bottom(x.clone()).unwrap();
1044 a.move_top(y).unwrap();
1045 x.move_after(z.clone()).unwrap();
1046 z.move_before(b).unwrap();
1047 node.move_bottom(c).unwrap();
1048
1049 assert!(matches!(
1050 tree
1051 .get_node_by_path(["a", "y"], false)
1052 .unwrap()
1053 .get_index_from_parent(),
1054 Ok(0)
1055 ));
1056 assert!(matches!(
1057 tree
1058 .get_node_by_path(["a", "x"], false)
1059 .unwrap()
1060 .get_index_from_parent(),
1061 Ok(1)
1062 ));
1063 assert!(matches!(
1064 tree
1065 .get_node_by_path(["a", "b"], false)
1066 .unwrap()
1067 .get_index_from_parent(),
1068 Ok(2)
1069 ));
1070 assert!(matches!(
1071 tree
1072 .get_node_by_path(["a", "z"], false)
1073 .unwrap()
1074 .get_index_from_parent(),
1075 Ok(3)
1076 ));
1077 assert!(matches!(
1078 tree
1079 .get_node_by_path(["c"], false)
1080 .unwrap()
1081 .get_index_from_parent(),
1082 Ok(1)
1083 ));
1084 }
1085
1086 #[test]
1087 fn test_paths() {
1088 let tree = Tree::new("root", "");
1089 let node = tree.get_node_by_line(0).unwrap();
1090
1091 node.insert_bottom(Node::new("x", ""));
1092 node.insert_bottom(Node::new("y", ""));
1093
1094 let x = tree.get_node_by_path(["x"], false).unwrap();
1095 x.insert_bottom(Node::new("a", ""));
1096 x.insert_bottom(Node::new("b", ""));
1097 x.insert_bottom(Node::new("c", ""));
1098
1099 assert_eq!(
1100 node.paths("", NodeFilter::Always),
1101 vec!["", "/x", "/x/a", "/x/b", "/x/c", "/y"],
1102 );
1103 }
1104
1105 #[test]
1106 fn data() {
1107 let node = Node::new("test", "");
1108
1109 assert_eq!(node.data(), None);
1110
1111 assert!(matches!(
1112 node.set_data(NodeData::file("/tmp/foo.md")),
1113 Ok(())
1114 ));
1115 assert_eq!(node.data(), Some(NodeData::file("/tmp/foo.md")));
1116
1117 assert!(matches!(
1118 node.set_data(NodeData::file("/tmp/bar.rs")),
1119 Err(NodeError::FileDataAlreadyExists)
1120 ));
1121 assert_eq!(node.data(), Some(NodeData::file("/tmp/foo.md")));
1122
1123 assert!(matches!(
1124 node.set_data(NodeData::link("https://foo.bar")),
1125 Err(NodeError::MismatchDataType)
1126 ));
1127 }
1128}