liwe/graph/
squash_iter.rs1use 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}