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}