1use std::collections::HashMap;
4use std::sync::Arc;
5use parking_lot::RwLock;
6
7use crate::error::{Error, Result};
8use crate::glow::{
9 EmberValue, ParameterType, ParameterAccess, MatrixType, MatrixAddressingMode,
10 TupleItemDescription, StringIntegerPair, Label,
11 EmberPath, GlowElement, GlowRoot, GlowNode, GlowParameter,
12 GlowFunction, GlowMatrix, GlowConnection, parse_path,
13};
14
15pub type TreeNodeRef = Arc<RwLock<TreeNode>>;
17
18#[derive(Debug, Default)]
20pub struct EmberTree {
21 children: HashMap<i32, TreeNodeRef>,
23 path_index: HashMap<String, TreeNodeRef>,
25}
26
27impl EmberTree {
28 pub fn new() -> Self {
30 EmberTree::default()
31 }
32
33 pub fn add_root_child(&mut self, node: TreeNode) -> TreeNodeRef {
35 let number = node.number();
36 let node_ref = Arc::new(RwLock::new(node));
37 self.children.insert(number, Arc::clone(&node_ref));
38 self.update_path_index(&node_ref, vec![number]);
39 node_ref
40 }
41
42 pub fn get_child(&self, number: i32) -> Option<TreeNodeRef> {
44 self.children.get(&number).cloned()
45 }
46
47 pub fn children(&self) -> impl Iterator<Item = &TreeNodeRef> {
49 self.children.values()
50 }
51
52 pub fn get_by_path(&self, path: &[i32]) -> Option<TreeNodeRef> {
54 if path.is_empty() {
55 return None;
56 }
57
58 let path_str = path.iter()
59 .map(|n| n.to_string())
60 .collect::<Vec<_>>()
61 .join(".");
62
63 if let Some(node) = self.path_index.get(&path_str) {
64 return Some(Arc::clone(node));
65 }
66
67 let mut current = self.get_child(path[0])?;
69
70 for &number in &path[1..] {
71 let node = current.read();
72 let child = node.get_child(number)?;
73 drop(node);
74 current = child;
75 }
76
77 Some(current)
78 }
79
80 pub fn get_by_path_str(&self, path: &str) -> Result<Option<TreeNodeRef>> {
82 let path = parse_path(path)?;
83 Ok(self.get_by_path(&path))
84 }
85
86 pub fn update_from_glow(&mut self, root: &GlowRoot) {
88 for element in &root.elements {
89 self.update_element(element, vec![]);
90 }
91 }
92
93 fn update_element(&mut self, element: &GlowElement, parent_path: Vec<i32>) {
95 match element {
96 GlowElement::Node(node) => {
97 let mut path = parent_path.clone();
98 path.push(node.number);
99
100 let tree_node = self.ensure_node(&path);
101 {
102 let mut n = tree_node.write();
103 n.update_from_glow_node(node);
104 }
105
106 for child in &node.children {
107 self.update_element(child, path.clone());
108 }
109 }
110 GlowElement::Parameter(param) => {
111 let mut path = parent_path.clone();
112 path.push(param.number);
113
114 let tree_node = self.ensure_node(&path);
115 {
116 let mut n = tree_node.write();
117 n.update_from_glow_parameter(param);
118 }
119 }
120 GlowElement::Function(func) => {
121 let mut path = parent_path.clone();
122 path.push(func.number);
123
124 let tree_node = self.ensure_node(&path);
125 {
126 let mut n = tree_node.write();
127 n.update_from_glow_function(func);
128 }
129 }
130 GlowElement::Matrix(matrix) => {
131 let mut path = parent_path.clone();
132 path.push(matrix.number);
133
134 let tree_node = self.ensure_node(&path);
135 {
136 let mut n = tree_node.write();
137 n.update_from_glow_matrix(matrix);
138 }
139 }
140 GlowElement::QualifiedNode(path, node) => {
141 let tree_node = self.ensure_node(path);
142 {
143 let mut n = tree_node.write();
144 n.update_from_glow_node(node);
145 }
146
147 for child in &node.children {
148 self.update_element(child, path.clone());
149 }
150 }
151 GlowElement::QualifiedParameter(path, param) => {
152 let tree_node = self.ensure_node(path);
153 {
154 let mut n = tree_node.write();
155 n.update_from_glow_parameter(param);
156 }
157 }
158 GlowElement::QualifiedFunction(path, func) => {
159 let tree_node = self.ensure_node(path);
160 {
161 let mut n = tree_node.write();
162 n.update_from_glow_function(func);
163 }
164 }
165 GlowElement::QualifiedMatrix(path, matrix) => {
166 let tree_node = self.ensure_node(path);
167 {
168 let mut n = tree_node.write();
169 n.update_from_glow_matrix(matrix);
170 }
171 }
172 _ => {}
173 }
174 }
175
176 fn ensure_node(&mut self, path: &[i32]) -> TreeNodeRef {
178 if path.is_empty() {
179 panic!("Cannot ensure node at empty path");
180 }
181
182 if let Some(node) = self.get_by_path(path) {
184 return node;
185 }
186
187 if !self.children.contains_key(&path[0]) {
189 let new_node = Arc::new(RwLock::new(TreeNode::new_node(path[0])));
190 self.children.insert(path[0], Arc::clone(&new_node));
191 let path_str = path[0].to_string();
192 self.path_index.insert(path_str, new_node);
193 }
194
195 let root_node = Arc::clone(self.children.get(&path[0]).unwrap());
196
197 if path.len() == 1 {
198 return root_node;
199 }
200
201 let mut current = root_node;
203 let mut current_path = vec![path[0]];
204
205 for &number in &path[1..] {
206 current_path.push(number);
207 let child = {
208 let mut node = current.write();
209 if let Some(existing) = node.get_child(number) {
210 existing
211 } else {
212 let new_child = Arc::new(RwLock::new(TreeNode::new_node(number)));
213 node.add_child(Arc::clone(&new_child));
214 new_child
215 }
216 };
217 let path_str = current_path.iter()
218 .map(|n| n.to_string())
219 .collect::<Vec<_>>()
220 .join(".");
221 self.path_index.insert(path_str, Arc::clone(&child));
222 current = child;
223 }
224
225 current
226 }
227
228 fn update_path_index(&mut self, node: &TreeNodeRef, path: Vec<i32>) {
230 let path_str = path.iter()
231 .map(|n| n.to_string())
232 .collect::<Vec<_>>()
233 .join(".");
234 self.path_index.insert(path_str, Arc::clone(node));
235 }
236
237 pub fn clear(&mut self) {
239 self.children.clear();
240 self.path_index.clear();
241 }
242
243 pub fn to_glow_elements(&self) -> Vec<GlowElement> {
245 self.children.values()
246 .map(|node| node.read().to_glow_element())
247 .collect()
248 }
249}
250
251#[derive(Debug, Clone)]
253pub enum NodeContents {
254 Node {
256 identifier: Option<String>,
257 description: Option<String>,
258 is_root: Option<bool>,
259 is_online: Option<bool>,
260 schema_identifiers: Option<String>,
261 },
262 Parameter {
264 identifier: Option<String>,
265 description: Option<String>,
266 value: Option<EmberValue>,
267 minimum: Option<EmberValue>,
268 maximum: Option<EmberValue>,
269 access: Option<ParameterAccess>,
270 format: Option<String>,
271 enumeration: Option<String>,
272 factor: Option<i32>,
273 is_online: Option<bool>,
274 formula: Option<String>,
275 step: Option<i32>,
276 default: Option<EmberValue>,
277 parameter_type: Option<ParameterType>,
278 stream_identifier: Option<i32>,
279 enum_map: Vec<StringIntegerPair>,
280 },
281 Function {
283 identifier: Option<String>,
284 description: Option<String>,
285 arguments: Vec<TupleItemDescription>,
286 result: Vec<TupleItemDescription>,
287 },
288 Matrix {
290 identifier: Option<String>,
291 description: Option<String>,
292 matrix_type: Option<MatrixType>,
293 addressing_mode: Option<MatrixAddressingMode>,
294 target_count: Option<i32>,
295 source_count: Option<i32>,
296 max_connections_per_target: Option<i32>,
297 max_total_connections: Option<i32>,
298 targets: Vec<i32>,
299 sources: Vec<i32>,
300 connections: Vec<GlowConnection>,
301 labels: Vec<Label>,
302 },
303}
304
305impl Default for NodeContents {
306 fn default() -> Self {
307 NodeContents::Node {
308 identifier: None,
309 description: None,
310 is_root: None,
311 is_online: None,
312 schema_identifiers: None,
313 }
314 }
315}
316
317#[derive(Debug)]
319pub struct TreeNode {
320 number: i32,
322 contents: NodeContents,
324 children: HashMap<i32, TreeNodeRef>,
326}
327
328impl TreeNode {
329 pub fn new_node(number: i32) -> Self {
331 TreeNode {
332 number,
333 contents: NodeContents::Node {
334 identifier: None,
335 description: None,
336 is_root: None,
337 is_online: None,
338 schema_identifiers: None,
339 },
340 children: HashMap::new(),
341 }
342 }
343
344 pub fn new_parameter(number: i32, value: EmberValue) -> Self {
346 TreeNode {
347 number,
348 contents: NodeContents::Parameter {
349 identifier: None,
350 description: None,
351 value: Some(value),
352 minimum: None,
353 maximum: None,
354 access: Some(ParameterAccess::ReadWrite),
355 format: None,
356 enumeration: None,
357 factor: None,
358 is_online: None,
359 formula: None,
360 step: None,
361 default: None,
362 parameter_type: None,
363 stream_identifier: None,
364 enum_map: vec![],
365 },
366 children: HashMap::new(),
367 }
368 }
369
370 pub fn number(&self) -> i32 {
372 self.number
373 }
374
375 pub fn contents(&self) -> &NodeContents {
377 &self.contents
378 }
379
380 pub fn contents_mut(&mut self) -> &mut NodeContents {
382 &mut self.contents
383 }
384
385 pub fn identifier(&self) -> Option<&str> {
387 match &self.contents {
388 NodeContents::Node { identifier, .. } => identifier.as_deref(),
389 NodeContents::Parameter { identifier, .. } => identifier.as_deref(),
390 NodeContents::Function { identifier, .. } => identifier.as_deref(),
391 NodeContents::Matrix { identifier, .. } => identifier.as_deref(),
392 }
393 }
394
395 pub fn description(&self) -> Option<&str> {
397 match &self.contents {
398 NodeContents::Node { description, .. } => description.as_deref(),
399 NodeContents::Parameter { description, .. } => description.as_deref(),
400 NodeContents::Function { description, .. } => description.as_deref(),
401 NodeContents::Matrix { description, .. } => description.as_deref(),
402 }
403 }
404
405 pub fn is_node(&self) -> bool {
407 matches!(self.contents, NodeContents::Node { .. })
408 }
409
410 pub fn is_parameter(&self) -> bool {
412 matches!(self.contents, NodeContents::Parameter { .. })
413 }
414
415 pub fn is_function(&self) -> bool {
417 matches!(self.contents, NodeContents::Function { .. })
418 }
419
420 pub fn is_matrix(&self) -> bool {
422 matches!(self.contents, NodeContents::Matrix { .. })
423 }
424
425 pub fn value(&self) -> Option<&EmberValue> {
427 match &self.contents {
428 NodeContents::Parameter { value, .. } => value.as_ref(),
429 _ => None,
430 }
431 }
432
433 pub fn set_value(&mut self, new_value: EmberValue) {
435 if let NodeContents::Parameter { value, .. } = &mut self.contents {
436 *value = Some(new_value);
437 }
438 }
439
440 pub fn add_child(&mut self, child: TreeNodeRef) {
442 let number = child.read().number;
443 self.children.insert(number, child);
444 }
445
446 pub fn get_child(&self, number: i32) -> Option<TreeNodeRef> {
448 self.children.get(&number).cloned()
449 }
450
451 pub fn children(&self) -> impl Iterator<Item = &TreeNodeRef> {
453 self.children.values()
454 }
455
456 pub fn update_from_glow_node(&mut self, glow: &GlowNode) {
458 self.contents = NodeContents::Node {
459 identifier: glow.identifier.clone(),
460 description: glow.description.clone(),
461 is_root: glow.is_root,
462 is_online: glow.is_online,
463 schema_identifiers: glow.schema_identifiers.clone(),
464 };
465 }
466
467 pub fn update_from_glow_parameter(&mut self, glow: &GlowParameter) {
469 self.contents = NodeContents::Parameter {
470 identifier: glow.identifier.clone(),
471 description: glow.description.clone(),
472 value: glow.value.clone(),
473 minimum: glow.minimum.clone(),
474 maximum: glow.maximum.clone(),
475 access: glow.access,
476 format: glow.format.clone(),
477 enumeration: glow.enumeration.clone(),
478 factor: glow.factor,
479 is_online: glow.is_online,
480 formula: glow.formula.clone(),
481 step: glow.step,
482 default: glow.default.clone(),
483 parameter_type: glow.parameter_type,
484 stream_identifier: glow.stream_identifier,
485 enum_map: glow.enum_map.clone(),
486 };
487 }
488
489 pub fn update_from_glow_function(&mut self, glow: &GlowFunction) {
491 self.contents = NodeContents::Function {
492 identifier: glow.identifier.clone(),
493 description: glow.description.clone(),
494 arguments: glow.arguments.clone(),
495 result: glow.result.clone(),
496 };
497 }
498
499 pub fn update_from_glow_matrix(&mut self, glow: &GlowMatrix) {
501 self.contents = NodeContents::Matrix {
502 identifier: glow.identifier.clone(),
503 description: glow.description.clone(),
504 matrix_type: glow.matrix_type,
505 addressing_mode: glow.addressing_mode,
506 target_count: glow.target_count,
507 source_count: glow.source_count,
508 max_connections_per_target: glow.max_connections_per_target,
509 max_total_connections: glow.max_total_connections,
510 targets: glow.targets.clone(),
511 sources: glow.sources.clone(),
512 connections: glow.connections.clone(),
513 labels: glow.labels.clone(),
514 };
515 }
516
517 pub fn to_glow_element(&self) -> GlowElement {
519 match &self.contents {
520 NodeContents::Node { identifier, description, is_root, is_online, schema_identifiers } => {
521 let mut node = GlowNode::new(self.number);
522 node.identifier = identifier.clone();
523 node.description = description.clone();
524 node.is_root = *is_root;
525 node.is_online = *is_online;
526 node.schema_identifiers = schema_identifiers.clone();
527 GlowElement::Node(node)
529 }
530 NodeContents::Parameter { identifier, description, value, minimum, maximum, access, format, enumeration, factor, is_online, formula, step, default, parameter_type, stream_identifier, enum_map } => {
531 let mut param = GlowParameter::new(self.number);
532 param.identifier = identifier.clone();
533 param.description = description.clone();
534 param.value = value.clone();
535 param.minimum = minimum.clone();
536 param.maximum = maximum.clone();
537 param.access = *access;
538 param.format = format.clone();
539 param.enumeration = enumeration.clone();
540 param.factor = *factor;
541 param.is_online = *is_online;
542 param.formula = formula.clone();
543 param.step = *step;
544 param.default = default.clone();
545 param.parameter_type = *parameter_type;
546 param.stream_identifier = *stream_identifier;
547 param.enum_map = enum_map.clone();
548 GlowElement::Parameter(param)
549 }
550 NodeContents::Function { identifier, description, arguments, result } => {
551 let mut func = GlowFunction::new(self.number);
552 func.identifier = identifier.clone();
553 func.description = description.clone();
554 func.arguments = arguments.clone();
555 func.result = result.clone();
556 GlowElement::Function(func)
557 }
558 NodeContents::Matrix { identifier, description, matrix_type, addressing_mode, target_count, source_count, max_connections_per_target, max_total_connections, targets, sources, connections, labels } => {
559 let mut matrix = GlowMatrix::new(self.number);
560 matrix.identifier = identifier.clone();
561 matrix.description = description.clone();
562 matrix.matrix_type = *matrix_type;
563 matrix.addressing_mode = *addressing_mode;
564 matrix.target_count = *target_count;
565 matrix.source_count = *source_count;
566 matrix.max_connections_per_target = *max_connections_per_target;
567 matrix.max_total_connections = *max_total_connections;
568 matrix.targets = targets.clone();
569 matrix.sources = sources.clone();
570 matrix.connections = connections.clone();
571 matrix.labels = labels.clone();
572 GlowElement::Matrix(matrix)
573 }
574 }
575 }
576
577 pub fn to_qualified_glow_element(&self, path: &EmberPath) -> GlowElement {
580 match &self.contents {
581 NodeContents::Node { identifier, description, is_root, is_online, schema_identifiers } => {
582 let mut node = GlowNode::new(self.number);
583 node.identifier = identifier.clone();
584 node.description = description.clone();
585 node.is_root = *is_root;
586 node.is_online = *is_online;
587 node.schema_identifiers = schema_identifiers.clone();
588 GlowElement::QualifiedNode(path.clone(), node)
589 }
590 NodeContents::Parameter { identifier, description, value, minimum, maximum, access, format, enumeration, factor, is_online, formula, step, default, parameter_type, stream_identifier, enum_map } => {
591 let mut param = GlowParameter::new(self.number);
592 param.identifier = identifier.clone();
593 param.description = description.clone();
594 param.value = value.clone();
595 param.minimum = minimum.clone();
596 param.maximum = maximum.clone();
597 param.access = *access;
598 param.format = format.clone();
599 param.enumeration = enumeration.clone();
600 param.factor = *factor;
601 param.is_online = *is_online;
602 param.formula = formula.clone();
603 param.step = *step;
604 param.default = default.clone();
605 param.parameter_type = *parameter_type;
606 param.stream_identifier = *stream_identifier;
607 param.enum_map = enum_map.clone();
608 GlowElement::QualifiedParameter(path.clone(), param)
609 }
610 NodeContents::Function { identifier, description, arguments, result } => {
611 let mut func = GlowFunction::new(self.number);
612 func.identifier = identifier.clone();
613 func.description = description.clone();
614 func.arguments = arguments.clone();
615 func.result = result.clone();
616 GlowElement::QualifiedFunction(path.clone(), func)
617 }
618 NodeContents::Matrix { identifier, description, matrix_type, addressing_mode, target_count, source_count, max_connections_per_target, max_total_connections, targets, sources, connections, labels } => {
619 let mut matrix = GlowMatrix::new(self.number);
620 matrix.identifier = identifier.clone();
621 matrix.description = description.clone();
622 matrix.matrix_type = *matrix_type;
623 matrix.addressing_mode = *addressing_mode;
624 matrix.target_count = *target_count;
625 matrix.source_count = *source_count;
626 matrix.max_connections_per_target = *max_connections_per_target;
627 matrix.max_total_connections = *max_total_connections;
628 matrix.targets = targets.clone();
629 matrix.sources = sources.clone();
630 matrix.connections = connections.clone();
631 matrix.labels = labels.clone();
632 GlowElement::QualifiedMatrix(path.clone(), matrix)
633 }
634 }
635 }
636}