eure_document/plan/
traverse.rs1use alloc::vec::Vec;
4
5use alloc::string::ToString;
6
7use crate::document::node::NodeValue;
8use crate::document::{EureDocument, NodeId};
9use crate::path::{ArrayIndexKind, PathSegment};
10use crate::value::{ObjectKey, PartialObjectKey};
11
12pub fn all_reachable_ids(doc: &EureDocument) -> Vec<NodeId> {
15 let mut out = Vec::new();
16 let mut stack = alloc::vec![doc.get_root_id()];
17 let mut seen = Vec::new();
18 while let Some(id) = stack.pop() {
19 if seen.contains(&id) {
20 continue;
21 }
22 seen.push(id);
23 out.push(id);
24 let node = doc.node(id);
25 let mut children: Vec<NodeId> = Vec::new();
27 for (_, &ext) in node.extensions.iter() {
28 children.push(ext);
29 }
30 match &node.content {
31 NodeValue::Map(map) => {
32 for (_, &cid) in map.iter() {
33 children.push(cid);
34 }
35 }
36 NodeValue::PartialMap(pm) => {
37 for (_, &cid) in pm.iter() {
38 children.push(cid);
39 }
40 }
41 NodeValue::Array(arr) => {
42 for &cid in arr.iter() {
43 children.push(cid);
44 }
45 }
46 NodeValue::Tuple(tup) => {
47 for &cid in tup.iter() {
48 children.push(cid);
49 }
50 }
51 _ => {}
52 }
53 for child in children.into_iter().rev() {
54 stack.push(child);
55 }
56 }
57 out.sort_by_key(|id| id.0);
61 out
62}
63
64pub fn children_of(doc: &EureDocument, parent: NodeId) -> Vec<(PathSegment, NodeId)> {
68 let mut out = Vec::new();
69 let node = doc.node(parent);
70 for (ident, &child) in node.extensions.iter() {
71 out.push((PathSegment::Extension(ident.clone()), child));
72 }
73 match &node.content {
74 NodeValue::Map(map) => {
75 for (key, &child) in map.iter() {
76 out.push((PathSegment::Value(key.clone()), child));
77 }
78 }
79 NodeValue::PartialMap(pm) => {
80 for (key, &child) in pm.iter() {
81 out.push((PathSegment::from_partial_object_key(key.clone()), child));
82 }
83 }
84 NodeValue::Array(arr) => {
85 for (i, &child) in arr.iter().enumerate() {
86 out.push((PathSegment::ArrayIndex(ArrayIndexKind::Specific(i)), child));
87 }
88 }
89 NodeValue::Tuple(tup) => {
90 for (i, &child) in tup.iter().enumerate() {
91 out.push((PathSegment::TupleIndex(i as u8), child));
92 }
93 }
94 _ => {}
95 }
96 out
97}
98
99pub fn child_node_id(
105 doc: &EureDocument,
106 parent_id: NodeId,
107 segment: &PathSegment,
108) -> Option<NodeId> {
109 let parent = doc.node(parent_id);
110 match segment {
111 PathSegment::Extension(ext) => parent.extensions.get(ext).copied(),
112 PathSegment::Ident(ident) => match &parent.content {
113 NodeValue::Map(map) => map.get(&ObjectKey::String(ident.to_string())).copied(),
114 NodeValue::PartialMap(map) => map
115 .find(&PartialObjectKey::String(ident.to_string()))
116 .copied(),
117 _ => None,
118 },
119 PathSegment::Value(key) => match &parent.content {
120 NodeValue::Map(map) => map.get(key).copied(),
121 NodeValue::PartialMap(map) => map.find(&PartialObjectKey::from(key.clone())).copied(),
122 _ => None,
123 },
124 PathSegment::PartialValue(key) => match &parent.content {
125 NodeValue::Map(map) => ObjectKey::try_from(key.clone())
126 .ok()
127 .and_then(|object_key| map.get(&object_key))
128 .copied(),
129 NodeValue::PartialMap(map) => map.find(key).copied(),
130 _ => None,
131 },
132 PathSegment::ArrayIndex(index) => match &parent.content {
133 NodeValue::Array(array) => match index {
134 ArrayIndexKind::Specific(i) => array.get(*i),
135 ArrayIndexKind::Push | ArrayIndexKind::Current => None,
136 },
137 _ => None,
138 },
139 PathSegment::TupleIndex(index) => match &parent.content {
140 NodeValue::Tuple(tuple) => tuple.get(*index as usize),
141 _ => None,
142 },
143 PathSegment::HoleKey(label) => match &parent.content {
144 NodeValue::PartialMap(map) => map.find(&PartialObjectKey::Hole(label.clone())).copied(),
145 _ => None,
146 },
147 }
148}