1use crate::error::{GlowError, Result};
4use crate::ber::{Tag, BerReader, BerWriter, BerValue};
5use super::tags;
6use super::element::EmberValue;
7
8pub type EmberPath = Vec<i32>;
10
11pub fn parse_path(path: &str) -> Result<EmberPath> {
13 if path.is_empty() {
14 return Ok(vec![]);
15 }
16
17 path.split('.')
18 .map(|s| {
19 s.parse::<i32>().map_err(|_| {
20 GlowError::InvalidPath(format!("invalid path component: {}", s)).into()
21 })
22 })
23 .collect()
24}
25
26pub fn format_path(path: &EmberPath) -> String {
28 path.iter()
29 .map(|n| n.to_string())
30 .collect::<Vec<_>>()
31 .join(".")
32}
33
34#[derive(Debug, Clone, Default)]
36pub struct GlowRoot {
37 pub elements: Vec<GlowElement>,
39 pub invocation_results: Vec<InvocationResult>,
41 pub streams: Vec<StreamEntry>,
43}
44
45impl GlowRoot {
46 pub fn new() -> Self {
48 GlowRoot::default()
49 }
50
51 pub fn with_elements(elements: Vec<GlowElement>) -> Self {
53 GlowRoot {
54 elements,
55 ..Default::default()
56 }
57 }
58
59 pub fn get_directory() -> Self {
61 GlowRoot {
62 elements: vec![GlowElement::Command(GlowCommand::GetDirectory)],
63 ..Default::default()
64 }
65 }
66
67 pub fn add_element(&mut self, element: GlowElement) {
69 self.elements.push(element);
70 }
71
72 pub fn is_empty(&self) -> bool {
74 self.elements.is_empty()
75 && self.invocation_results.is_empty()
76 && self.streams.is_empty()
77 }
78}
79
80#[derive(Debug, Clone)]
82pub enum GlowElement {
83 Node(GlowNode),
85 Parameter(GlowParameter),
87 Function(GlowFunction),
89 Matrix(GlowMatrix),
91 Command(GlowCommand),
93 QualifiedNode(EmberPath, GlowNode),
95 QualifiedParameter(EmberPath, GlowParameter),
97 QualifiedFunction(EmberPath, GlowFunction),
99 QualifiedMatrix(EmberPath, GlowMatrix),
101 Template(GlowTemplate),
103}
104
105impl GlowElement {
106 pub fn number(&self) -> Option<i32> {
108 match self {
109 GlowElement::Node(n) => Some(n.number),
110 GlowElement::Parameter(p) => Some(p.number),
111 GlowElement::Function(f) => Some(f.number),
112 GlowElement::Matrix(m) => Some(m.number),
113 _ => None,
114 }
115 }
116
117 pub fn path(&self) -> Option<&EmberPath> {
119 match self {
120 GlowElement::QualifiedNode(path, _) => Some(path),
121 GlowElement::QualifiedParameter(path, _) => Some(path),
122 GlowElement::QualifiedFunction(path, _) => Some(path),
123 GlowElement::QualifiedMatrix(path, _) => Some(path),
124 _ => None,
125 }
126 }
127
128 pub fn is_node(&self) -> bool {
130 matches!(self, GlowElement::Node(_) | GlowElement::QualifiedNode(_, _))
131 }
132
133 pub fn is_parameter(&self) -> bool {
135 matches!(self, GlowElement::Parameter(_) | GlowElement::QualifiedParameter(_, _))
136 }
137
138 pub fn is_function(&self) -> bool {
140 matches!(self, GlowElement::Function(_) | GlowElement::QualifiedFunction(_, _))
141 }
142
143 pub fn is_matrix(&self) -> bool {
145 matches!(self, GlowElement::Matrix(_) | GlowElement::QualifiedMatrix(_, _))
146 }
147
148 pub fn is_command(&self) -> bool {
150 matches!(self, GlowElement::Command(_))
151 }
152}
153
154#[derive(Debug, Clone, Default)]
156pub struct GlowNode {
157 pub number: i32,
159 pub identifier: Option<String>,
161 pub description: Option<String>,
163 pub is_root: Option<bool>,
165 pub is_online: Option<bool>,
167 pub schema_identifiers: Option<String>,
169 pub template_reference: Option<EmberPath>,
171 pub children: Vec<GlowElement>,
173}
174
175impl GlowNode {
176 pub fn new(number: i32) -> Self {
178 GlowNode {
179 number,
180 ..Default::default()
181 }
182 }
183
184 pub fn with_identifier(number: i32, identifier: &str) -> Self {
186 GlowNode {
187 number,
188 identifier: Some(identifier.to_string()),
189 ..Default::default()
190 }
191 }
192
193 pub fn description(mut self, description: &str) -> Self {
195 self.description = Some(description.to_string());
196 self
197 }
198
199 pub fn is_root(mut self, is_root: bool) -> Self {
201 self.is_root = Some(is_root);
202 self
203 }
204
205 pub fn add_child(&mut self, child: GlowElement) {
207 self.children.push(child);
208 }
209}
210
211#[derive(Debug, Clone, Default)]
213pub struct GlowParameter {
214 pub number: i32,
216 pub identifier: Option<String>,
218 pub description: Option<String>,
220 pub value: Option<EmberValue>,
222 pub minimum: Option<EmberValue>,
224 pub maximum: Option<EmberValue>,
226 pub access: Option<super::element::ParameterAccess>,
228 pub format: Option<String>,
230 pub enumeration: Option<String>,
232 pub factor: Option<i32>,
234 pub is_online: Option<bool>,
236 pub formula: Option<String>,
238 pub step: Option<i32>,
240 pub default: Option<EmberValue>,
242 pub parameter_type: Option<super::element::ParameterType>,
244 pub stream_identifier: Option<i32>,
246 pub enum_map: Vec<super::element::StringIntegerPair>,
248 pub stream_descriptor: Option<super::element::StreamDescriptor>,
250 pub schema_identifiers: Option<String>,
252 pub template_reference: Option<EmberPath>,
254 pub children: Vec<GlowElement>,
256}
257
258impl GlowParameter {
259 pub fn new(number: i32) -> Self {
261 GlowParameter {
262 number,
263 ..Default::default()
264 }
265 }
266
267 pub fn with_value(number: i32, identifier: &str, value: EmberValue) -> Self {
269 GlowParameter {
270 number,
271 identifier: Some(identifier.to_string()),
272 value: Some(value),
273 ..Default::default()
274 }
275 }
276
277 pub fn description(mut self, description: &str) -> Self {
279 self.description = Some(description.to_string());
280 self
281 }
282
283 pub fn access(mut self, access: super::element::ParameterAccess) -> Self {
285 self.access = Some(access);
286 self
287 }
288
289 pub fn minimum(mut self, min: EmberValue) -> Self {
291 self.minimum = Some(min);
292 self
293 }
294
295 pub fn maximum(mut self, max: EmberValue) -> Self {
297 self.maximum = Some(max);
298 self
299 }
300}
301
302#[derive(Debug, Clone, Default)]
304pub struct GlowFunction {
305 pub number: i32,
307 pub identifier: Option<String>,
309 pub description: Option<String>,
311 pub arguments: Vec<super::element::TupleItemDescription>,
313 pub result: Vec<super::element::TupleItemDescription>,
315 pub template_reference: Option<EmberPath>,
317 pub children: Vec<GlowElement>,
319}
320
321impl GlowFunction {
322 pub fn new(number: i32) -> Self {
324 GlowFunction {
325 number,
326 ..Default::default()
327 }
328 }
329
330 pub fn with_identifier(number: i32, identifier: &str) -> Self {
332 GlowFunction {
333 number,
334 identifier: Some(identifier.to_string()),
335 ..Default::default()
336 }
337 }
338}
339
340#[derive(Debug, Clone, Default)]
342pub struct GlowMatrix {
343 pub number: i32,
345 pub identifier: Option<String>,
347 pub description: Option<String>,
349 pub matrix_type: Option<super::element::MatrixType>,
351 pub addressing_mode: Option<super::element::MatrixAddressingMode>,
353 pub target_count: Option<i32>,
355 pub source_count: Option<i32>,
357 pub max_connections_per_target: Option<i32>,
359 pub max_total_connections: Option<i32>,
361 pub connection_parameters_location: Option<EmberPath>,
363 pub gain_parameter_number: Option<i32>,
365 pub labels: Vec<super::element::Label>,
367 pub schema_identifiers: Option<String>,
369 pub template_reference: Option<EmberPath>,
371 pub targets: Vec<i32>,
373 pub sources: Vec<i32>,
375 pub connections: Vec<GlowConnection>,
377 pub children: Vec<GlowElement>,
379}
380
381impl GlowMatrix {
382 pub fn new(number: i32) -> Self {
384 GlowMatrix {
385 number,
386 ..Default::default()
387 }
388 }
389
390 pub fn with_identifier(number: i32, identifier: &str) -> Self {
392 GlowMatrix {
393 number,
394 identifier: Some(identifier.to_string()),
395 ..Default::default()
396 }
397 }
398}
399
400#[derive(Debug, Clone, Default)]
402pub struct GlowConnection {
403 pub target: i32,
405 pub sources: Vec<i32>,
407 pub operation: Option<super::element::ConnectionOperation>,
409 pub disposition: Option<super::element::ConnectionDisposition>,
411}
412
413impl GlowConnection {
414 pub fn new(target: i32, sources: Vec<i32>) -> Self {
416 GlowConnection {
417 target,
418 sources,
419 ..Default::default()
420 }
421 }
422}
423
424#[derive(Debug, Clone, PartialEq)]
426pub enum GlowCommand {
427 Subscribe,
429 Unsubscribe,
431 GetDirectory,
433 Invoke {
435 invocation_id: i32,
437 arguments: Vec<EmberValue>,
439 },
440}
441
442impl GlowCommand {
443 pub fn number(&self) -> i32 {
445 match self {
446 GlowCommand::Subscribe => 1,
447 GlowCommand::Unsubscribe => 2,
448 GlowCommand::GetDirectory => 32,
449 GlowCommand::Invoke { .. } => 33,
450 }
451 }
452}
453
454#[derive(Debug, Clone, Default)]
456pub struct GlowTemplate {
457 pub number: i32,
459 pub element: Option<Box<GlowElement>>,
461 pub description: Option<String>,
463}
464
465#[derive(Debug, Clone)]
467pub struct InvocationResult {
468 pub invocation_id: i32,
470 pub success: bool,
472 pub result: Vec<EmberValue>,
474}
475
476impl InvocationResult {
477 pub fn success(invocation_id: i32, result: Vec<EmberValue>) -> Self {
479 InvocationResult {
480 invocation_id,
481 success: true,
482 result,
483 }
484 }
485
486 pub fn failure(invocation_id: i32) -> Self {
488 InvocationResult {
489 invocation_id,
490 success: false,
491 result: vec![],
492 }
493 }
494}
495
496#[derive(Debug, Clone)]
498pub struct StreamEntry {
499 pub stream_identifier: i32,
501 pub value: EmberValue,
503}
504
505impl StreamEntry {
506 pub fn new(stream_identifier: i32, value: EmberValue) -> Self {
508 StreamEntry { stream_identifier, value }
509 }
510}