liwe/graph/
squash_iter.rs

1use super::{Graph, GraphContext};
2use crate::model::node::Node;
3use crate::model::node::{NodeIter, NodePointer};
4use crate::model::NodeId;
5
6pub struct SquashIter<'a> {
7    id: NodeId,
8    depth: u8,
9    graph: &'a Graph,
10    resume_id: Option<NodeId>,
11}
12
13impl<'a> SquashIter<'a> {
14    #[allow(dead_code)]
15    pub fn new(graph: &'a Graph, id: NodeId, depth: u8) -> Self {
16        Self {
17            id,
18            depth,
19            graph,
20            resume_id: None,
21        }
22    }
23
24    fn next_referenced_id(&self) -> Option<NodeId> {
25        self.graph
26            .node(self.id)
27            .to_next()
28            .and_then(|n| n.ref_key())
29            .and_then(|key| self.graph.maybe_key(&key))
30            .and_then(|doc| doc.to_child())
31            .and_then(|node| node.id())
32    }
33
34    fn resume_next_referenced_id(&self) -> Option<NodeId> {
35        self.resume_id
36            .map(|id| self.graph.node(id))
37            .and_then(|n| n.to_next())
38            .and_then(|n| n.ref_key())
39            .and_then(|key| self.graph.maybe_key(&key))
40            .and_then(|doc| doc.to_child())
41            .and_then(|node| node.id())
42    }
43
44    fn resume_next_id(&self) -> Option<NodeId> {
45        self.resume_id
46            .and_then(|resume_id| self.graph.node(resume_id).to_next())
47            .and_then(|resume_next| resume_next.id())
48    }
49
50    fn child_referenced_id(&self) -> Option<NodeId> {
51        self.graph
52            .node(self.id)
53            .to_child()
54            .and_then(|n| n.ref_key())
55            .and_then(|key| self.graph.maybe_key(&key))
56            .and_then(|doc| doc.to_child())
57            .and_then(|node| node.id())
58    }
59
60    fn next_id(&self) -> Option<NodeId> {
61        self.graph.graph_node(self.id).next_id()
62    }
63
64    fn child_id(&self) -> Option<NodeId> {
65        self.graph.graph_node(self.id).child_id()
66    }
67}
68
69impl<'a> NodeIter<'a> for SquashIter<'a> {
70    fn next(&self) -> Option<Self> {
71        self.next_referenced_id()
72            .filter(|_| self.depth > 0)
73            .map(|id| SquashIter {
74                id,
75                depth: self.depth - 1,
76                resume_id: self.next_id(),
77                graph: self.graph,
78            })
79            .or(self
80                .resume_id
81                .filter(|_| self.next_id().is_none())
82                .and_then(|_| {
83                    self.resume_next_referenced_id()
84                        .filter(|_| self.depth > 0)
85                        .map(|id| SquashIter {
86                            id,
87                            depth: self.depth + 1,
88                            resume_id: self.resume_next_id(),
89                            graph: self.graph,
90                        })
91                        .or(self.resume_next_id().map(|id| SquashIter {
92                            id,
93                            depth: self.depth + 1,
94                            resume_id: None,
95                            graph: self.graph,
96                        }))
97                }))
98            .or(self.next_id().map(|id| SquashIter {
99                id,
100                depth: self.depth,
101                resume_id: self.resume_id,
102                graph: self.graph,
103            }))
104    }
105
106    fn child(&self) -> Option<Self> {
107        self.child_referenced_id()
108            .filter(|_| self.depth > 0)
109            .map(|id| SquashIter {
110                id,
111                depth: self.depth - 1,
112                resume_id: self.child_id(),
113                graph: self.graph,
114            })
115            .or(self.child_id().map(|id| SquashIter {
116                id,
117                depth: self.depth,
118                resume_id: None,
119                graph: self.graph,
120            }))
121    }
122
123    fn node(&self) -> Option<Node> {
124        {
125            let this = &self.graph;
126            let id = self.id;
127            this.node(id).node()
128        }
129    }
130}