rustla/doctree/walkers.rs
1/*!
2A submodule for doctree walker functions.
3
4Copyright © 2020 Santtu Söderholm
5*/
6
7use super::*;
8
9use crate::common::TraversalType;
10
11/// ---------
12/// Walkers
13/// ---------
14///
15/// Functions for walking to differents parts of the contained `TreeZipper`.
16/// These include ID-based searches, as well as criteria related to the
17/// contained data variant.
18impl DocTree {
19
20 /// Walks to the root of the contained tree zipper.
21 pub fn walk_to_root(mut self) -> Self {
22 self.tree = self.tree.walk_to_root();
23 self
24 }
25
26 /// The mother of all walkers. Performs a tree walk based on given `TraversalType`.
27 /// These include walking to a specific node id, but a reference to a `TreeNodeType`
28 /// might also be used in determining when to stop walking.
29 pub fn walk(mut self, traversal_type: TraversalType) -> Self {
30 // Always walk to tree root before starting the search/walk.
31 self.tree = self.tree.walk_to_root();
32
33 match traversal_type {
34 TraversalType::ID(id) => self.walk_to_node_with_id(id),
35 }
36 }
37
38 /// Walks to a `TreeNode` with a specific given ID.
39 /// Naively walks to the tree root before beginning the actual search,
40 /// in order to ensure that all nodes are traversed.
41 ///
42 /// Panic!s if a node with the given id is not found.
43 fn walk_to_node_with_id(mut self, id: NodeId) -> Self {
44 if id > self.node_count() {
45 panic!("No node with given ID. Computer says no...")
46 }
47
48 self.tree = match self.tree.walk_to_node_with_id(id) {
49 Ok(zipper) => zipper,
50 Err(zipper) => zipper,
51 };
52
53 self
54 }
55
56 /// Walks to a node with a given ID and the back again.
57 /// Panic!s, if the given target node id has not been entered into the tree.
58 fn walk_to_and_fro(self, to_id: NodeId, current_id: NodeId) -> Self {
59 if to_id > self.node_count() {
60 panic!("No node with given ID. Computer says no...")
61 }
62
63 todo!()
64 }
65}
66
67/// ---------
68/// Walkers
69/// ---------
70impl TreeZipper {
71
72 /// Walks to a specific node based on a given id,
73 /// using the NLR (pre-order) strategy.
74 pub fn walk_to_node_with_id(mut self, id: NodeId) -> Result<Self, Self> {
75 if self.node_id() == id {
76 return Ok(self);
77 }
78
79 let n_of_children = if let Some(children) = self.shared_node().shared_children() {
80 self.n_of_children()
81 } else {
82 match self.focus_on_parent() {
83 Ok(zipper) | Err(zipper) => return Err(zipper),
84 }
85 };
86
87 for ind in 0..n_of_children {
88 self = if let Ok(child) = self.focus_on_child(ind) {
89 child
90 } else {
91 unreachable!("This should not happen with enumerated children...")
92 };
93 match self.walk_to_node_with_id(id) {
94 Ok(zipper) => return Ok(zipper),
95 Err(zipper) => {
96 self = zipper;
97 continue;
98 }
99 }
100 }
101
102 self = match self.focus_on_parent() {
103 Ok(zipper) | Err(zipper) => zipper,
104 };
105 Err(self)
106 }
107}