use std::collections::{BTreeMap, BTreeSet};
use super::{UiAst, UiNode, UiNodeKind};
pub fn collect_pointers(ast: &UiAst) -> BTreeSet<String> {
let mut set = BTreeSet::new();
for node in &ast.roots {
collect_node_pointers(node, &mut set);
}
set
}
fn collect_node_pointers(node: &UiNode, out: &mut BTreeSet<String>) {
out.insert(node.pointer.clone());
match &node.kind {
UiNodeKind::Object { children, .. } => {
for child in children {
collect_node_pointers(child, out);
}
}
UiNodeKind::Composite { variants, .. } => {
for variant in variants {
collect_kind_pointers(&variant.node, out);
}
}
UiNodeKind::Array { item, .. } => {
collect_kind_pointers(item, out);
}
UiNodeKind::KeyValue { .. } => {}
UiNodeKind::Field { .. } => {}
}
}
fn collect_kind_pointers(kind: &UiNodeKind, out: &mut BTreeSet<String>) {
match kind {
UiNodeKind::Object { children, .. } => {
for child in children {
collect_node_pointers(child, out);
}
}
UiNodeKind::Composite { variants, .. } => {
for variant in variants {
collect_kind_pointers(&variant.node, out);
}
}
UiNodeKind::Array { item, .. } => {
collect_kind_pointers(item, out);
}
UiNodeKind::KeyValue { .. } => {}
UiNodeKind::Field { .. } => {}
}
}
pub type PointerIndex = BTreeMap<String, usize>;
pub fn build_pointer_index(ast: &UiAst) -> PointerIndex {
let mut index = PointerIndex::new();
let mut counter = 0usize;
for node in &ast.roots {
index_node(node, &mut counter, &mut index);
}
index
}
fn index_node(node: &UiNode, counter: &mut usize, out: &mut PointerIndex) {
let id = *counter;
out.insert(node.pointer.clone(), id);
*counter += 1;
match &node.kind {
UiNodeKind::Object { children, .. } => {
for child in children {
index_node(child, counter, out);
}
}
UiNodeKind::Composite { variants, .. } => {
for variant in variants {
index_kind(&variant.node, counter, out);
}
}
UiNodeKind::Array { item, .. } => {
index_kind(item, counter, out);
}
UiNodeKind::KeyValue { .. } => {}
UiNodeKind::Field { .. } => {}
}
}
fn index_kind(kind: &UiNodeKind, counter: &mut usize, out: &mut PointerIndex) {
match kind {
UiNodeKind::Object { children, .. } => {
for child in children {
index_node(child, counter, out);
}
}
UiNodeKind::Composite { variants, .. } => {
for variant in variants {
index_kind(&variant.node, counter, out);
}
}
UiNodeKind::Array { item, .. } => {
index_kind(item, counter, out);
}
UiNodeKind::KeyValue { .. } => {}
UiNodeKind::Field { .. } => {}
}
}