oxihuman_core/
tree_index.rs1#![allow(dead_code)]
4
5use std::collections::HashMap;
8
9#[allow(dead_code)]
11#[derive(Debug, Clone)]
12pub struct TreeNode {
13 pub id: u32,
14 pub label: String,
15 pub parent: Option<u32>,
16 pub children: Vec<u32>,
17}
18
19#[allow(dead_code)]
21#[derive(Debug, Clone, Default)]
22pub struct TreeIndex {
23 nodes: HashMap<u32, TreeNode>,
24 roots: Vec<u32>,
25 next_id: u32,
26}
27
28#[allow(dead_code)]
30pub fn new_tree_index() -> TreeIndex {
31 TreeIndex::default()
32}
33
34#[allow(dead_code)]
36pub fn ti_add_root(ti: &mut TreeIndex, label: &str) -> u32 {
37 let id = ti.next_id;
38 ti.next_id += 1;
39 ti.nodes.insert(
40 id,
41 TreeNode {
42 id,
43 label: label.to_string(),
44 parent: None,
45 children: Vec::new(),
46 },
47 );
48 ti.roots.push(id);
49 id
50}
51
52#[allow(dead_code)]
54pub fn ti_add_child(ti: &mut TreeIndex, parent_id: u32, label: &str) -> Option<u32> {
55 if !ti.nodes.contains_key(&parent_id) {
56 return None;
57 }
58 let id = ti.next_id;
59 ti.next_id += 1;
60 ti.nodes.insert(
61 id,
62 TreeNode {
63 id,
64 label: label.to_string(),
65 parent: Some(parent_id),
66 children: Vec::new(),
67 },
68 );
69 if let Some(parent) = ti.nodes.get_mut(&parent_id) {
70 parent.children.push(id);
71 }
72 Some(id)
73}
74
75#[allow(dead_code)]
77pub fn ti_label(ti: &TreeIndex, id: u32) -> Option<&str> {
78 ti.nodes.get(&id).map(|n| n.label.as_str())
79}
80
81#[allow(dead_code)]
83pub fn ti_parent(ti: &TreeIndex, id: u32) -> Option<u32> {
84 ti.nodes.get(&id).and_then(|n| n.parent)
85}
86
87#[allow(dead_code)]
89pub fn ti_children(ti: &TreeIndex, id: u32) -> Vec<u32> {
90 ti.nodes
91 .get(&id)
92 .map(|n| n.children.clone())
93 .unwrap_or_default()
94}
95
96#[allow(dead_code)]
98pub fn ti_count(ti: &TreeIndex) -> usize {
99 ti.nodes.len()
100}
101
102#[allow(dead_code)]
104pub fn ti_depth(ti: &TreeIndex, id: u32) -> usize {
105 let mut depth = 0;
106 let mut cur = id;
107 while let Some(p) = ti.nodes.get(&cur).and_then(|n| n.parent) {
108 cur = p;
109 depth += 1;
110 }
111 depth
112}
113
114#[allow(dead_code)]
116pub fn ti_descendants(ti: &TreeIndex, id: u32) -> Vec<u32> {
117 let mut result = Vec::new();
118 let mut queue = vec![id];
119 while !queue.is_empty() {
120 let cur = queue.remove(0);
121 if let Some(node) = ti.nodes.get(&cur) {
122 for &child in &node.children {
123 result.push(child);
124 queue.push(child);
125 }
126 }
127 }
128 result
129}
130
131#[allow(dead_code)]
133pub fn ti_roots(ti: &TreeIndex) -> &[u32] {
134 &ti.roots
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn test_add_root() {
143 let mut ti = new_tree_index();
144 let id = ti_add_root(&mut ti, "root");
145 assert_eq!(ti_label(&ti, id), Some("root"));
146 }
147
148 #[test]
149 fn test_add_child() {
150 let mut ti = new_tree_index();
151 let root = ti_add_root(&mut ti, "root");
152 let child = ti_add_child(&mut ti, root, "child").expect("should succeed");
153 assert_eq!(ti_parent(&ti, child), Some(root));
154 }
155
156 #[test]
157 fn test_children() {
158 let mut ti = new_tree_index();
159 let r = ti_add_root(&mut ti, "r");
160 let c1 = ti_add_child(&mut ti, r, "c1").expect("should succeed");
161 let c2 = ti_add_child(&mut ti, r, "c2").expect("should succeed");
162 let children = ti_children(&ti, r);
163 assert!(children.contains(&c1) && children.contains(&c2));
164 }
165
166 #[test]
167 fn test_depth() {
168 let mut ti = new_tree_index();
169 let r = ti_add_root(&mut ti, "r");
170 let c = ti_add_child(&mut ti, r, "c").expect("should succeed");
171 let gc = ti_add_child(&mut ti, c, "gc").expect("should succeed");
172 assert_eq!(ti_depth(&ti, r), 0);
173 assert_eq!(ti_depth(&ti, c), 1);
174 assert_eq!(ti_depth(&ti, gc), 2);
175 }
176
177 #[test]
178 fn test_descendants() {
179 let mut ti = new_tree_index();
180 let r = ti_add_root(&mut ti, "r");
181 let c = ti_add_child(&mut ti, r, "c").expect("should succeed");
182 ti_add_child(&mut ti, c, "gc").expect("should succeed");
183 let desc = ti_descendants(&ti, r);
184 assert_eq!(desc.len(), 2);
185 }
186
187 #[test]
188 fn test_count() {
189 let mut ti = new_tree_index();
190 let r = ti_add_root(&mut ti, "r");
191 ti_add_child(&mut ti, r, "c").expect("should succeed");
192 assert_eq!(ti_count(&ti), 2);
193 }
194
195 #[test]
196 fn test_roots_list() {
197 let mut ti = new_tree_index();
198 let r1 = ti_add_root(&mut ti, "r1");
199 let r2 = ti_add_root(&mut ti, "r2");
200 let roots = ti_roots(&ti);
201 assert!(roots.contains(&r1) && roots.contains(&r2));
202 }
203
204 #[test]
205 fn test_invalid_parent() {
206 let mut ti = new_tree_index();
207 let result = ti_add_child(&mut ti, 999, "x");
208 assert!(result.is_none());
209 }
210
211 #[test]
212 fn test_no_parent_for_root() {
213 let mut ti = new_tree_index();
214 let r = ti_add_root(&mut ti, "r");
215 assert!(ti_parent(&ti, r).is_none());
216 }
217}