1use std::cell::RefCell;
4use std::collections::HashMap;
5
6use viva_genapi_xml::{AccessMode, Addressing, BitField, EnumEntryDecl};
7pub use viva_genapi_xml::{NodeMeta, Representation, SkOutput, Visibility};
8
9use crate::swissknife::AstNode;
10
11#[derive(Debug)]
13pub enum Node {
14 Integer(IntegerNode),
16 Float(FloatNode),
18 Enum(EnumNode),
20 Boolean(BooleanNode),
22 Command(CommandNode),
24 Category(CategoryNode),
26 SwissKnife(SkNode),
28 Converter(ConverterNode),
30 IntConverter(IntConverterNode),
32 String(StringNode),
34}
35
36impl Node {
37 pub fn kind_name(&self) -> &'static str {
39 match self {
40 Node::Integer(_) => "Integer",
41 Node::Float(_) => "Float",
42 Node::Enum(_) => "Enumeration",
43 Node::Boolean(_) => "Boolean",
44 Node::Command(_) => "Command",
45 Node::Category(_) => "Category",
46 Node::SwissKnife(_) => "SwissKnife",
47 Node::Converter(_) => "Converter",
48 Node::IntConverter(_) => "IntConverter",
49 Node::String(_) => "StringReg",
50 }
51 }
52
53 pub fn access_mode(&self) -> Option<viva_genapi_xml::AccessMode> {
55 match self {
56 Node::Integer(n) => Some(n.access),
57 Node::Float(n) => Some(n.access),
58 Node::Enum(n) => Some(n.access),
59 Node::Boolean(n) => Some(n.access),
60 Node::Command(_) => Some(viva_genapi_xml::AccessMode::WO),
61 Node::Category(_) => None,
62 Node::SwissKnife(_) => Some(viva_genapi_xml::AccessMode::RO),
63 Node::Converter(_) => Some(viva_genapi_xml::AccessMode::RO),
64 Node::IntConverter(_) => Some(viva_genapi_xml::AccessMode::RO),
65 Node::String(n) => Some(n.access),
66 }
67 }
68
69 pub fn name(&self) -> &str {
71 match self {
72 Node::Integer(n) => &n.name,
73 Node::Float(n) => &n.name,
74 Node::Enum(n) => &n.name,
75 Node::Boolean(n) => &n.name,
76 Node::Command(n) => &n.name,
77 Node::Category(n) => &n.name,
78 Node::SwissKnife(n) => &n.name,
79 Node::Converter(n) => &n.name,
80 Node::IntConverter(n) => &n.name,
81 Node::String(n) => &n.name,
82 }
83 }
84
85 pub fn meta(&self) -> &NodeMeta {
87 match self {
88 Node::Integer(n) => &n.meta,
89 Node::Float(n) => &n.meta,
90 Node::Enum(n) => &n.meta,
91 Node::Boolean(n) => &n.meta,
92 Node::Command(n) => &n.meta,
93 Node::Category(n) => &n.meta,
94 Node::SwissKnife(n) => &n.meta,
95 Node::Converter(n) => &n.meta,
96 Node::IntConverter(n) => &n.meta,
97 Node::String(n) => &n.meta,
98 }
99 }
100
101 pub fn visibility(&self) -> Visibility {
103 self.meta().visibility
104 }
105
106 pub fn description(&self) -> Option<&str> {
108 self.meta().description.as_deref()
109 }
110
111 pub fn tooltip(&self) -> Option<&str> {
113 self.meta().tooltip.as_deref()
114 }
115
116 pub fn display_name(&self) -> Option<&str> {
118 self.meta().display_name.as_deref()
119 }
120
121 pub fn representation(&self) -> Option<Representation> {
123 self.meta().representation
124 }
125
126 pub(crate) fn invalidate_cache(&self) {
127 match self {
128 Node::Integer(node) => {
129 node.cache.replace(None);
130 node.raw_cache.replace(None);
131 }
132 Node::Float(node) => {
133 node.cache.replace(None);
134 }
135 Node::Enum(node) => node.invalidate(),
136 Node::Boolean(node) => {
137 node.cache.replace(None);
138 node.raw_cache.replace(None);
139 }
140 Node::SwissKnife(node) => {
141 node.cache.replace(None);
142 }
143 Node::Converter(node) => {
144 node.cache.replace(None);
145 }
146 Node::IntConverter(node) => {
147 node.cache.replace(None);
148 }
149 Node::String(node) => {
150 node.cache.replace(None);
151 }
152 Node::Command(_) | Node::Category(_) => {}
153 }
154 }
155}
156
157#[derive(Debug)]
159pub struct IntegerNode {
160 pub name: String,
162 pub meta: NodeMeta,
164 pub addressing: Option<Addressing>,
166 pub len: u32,
168 pub access: AccessMode,
170 pub min: i64,
172 pub max: i64,
174 pub inc: Option<i64>,
176 pub unit: Option<String>,
178 pub bitfield: Option<BitField>,
180 pub selectors: Vec<String>,
182 pub selected_if: Vec<(String, Vec<String>)>,
184 pub pvalue: Option<String>,
186 pub p_max: Option<String>,
188 pub p_min: Option<String>,
190 pub value: Option<i64>,
192 pub(crate) cache: RefCell<Option<i64>>,
193 pub(crate) raw_cache: RefCell<Option<Vec<u8>>>,
194}
195
196#[derive(Debug)]
198pub struct FloatNode {
199 pub name: String,
200 pub meta: NodeMeta,
202 pub addressing: Option<Addressing>,
204 pub access: AccessMode,
205 pub min: f64,
206 pub max: f64,
207 pub unit: Option<String>,
208 pub scale: Option<(i64, i64)>,
210 pub offset: Option<f64>,
212 pub selectors: Vec<String>,
213 pub selected_if: Vec<(String, Vec<String>)>,
214 pub pvalue: Option<String>,
216 pub(crate) cache: RefCell<Option<f64>>,
217}
218
219#[derive(Debug)]
221pub struct EnumNode {
222 pub name: String,
223 pub meta: NodeMeta,
225 pub addressing: Option<Addressing>,
227 pub access: AccessMode,
228 pub pvalue: Option<String>,
230 pub entries: Vec<EnumEntryDecl>,
231 pub default: Option<String>,
232 pub selectors: Vec<String>,
233 pub selected_if: Vec<(String, Vec<String>)>,
234 pub providers: Vec<String>,
235 pub(crate) value_cache: RefCell<Option<String>>,
236 pub(crate) mapping_cache: RefCell<Option<EnumMapping>>,
237}
238
239#[derive(Debug, Clone)]
240pub(crate) struct EnumMapping {
241 pub by_value: HashMap<i64, String>,
242 pub by_name: HashMap<String, i64>,
243}
244
245impl EnumNode {
246 pub(crate) fn invalidate(&self) {
247 self.value_cache.replace(None);
248 self.mapping_cache.replace(None);
249 }
250}
251
252#[derive(Debug)]
254pub struct BooleanNode {
255 pub name: String,
256 pub meta: NodeMeta,
258 pub addressing: Option<Addressing>,
260 pub len: u32,
261 pub access: AccessMode,
262 pub bitfield: Option<BitField>,
264 pub selectors: Vec<String>,
265 pub selected_if: Vec<(String, Vec<String>)>,
266 pub pvalue: Option<String>,
268 pub on_value: Option<i64>,
270 pub off_value: Option<i64>,
272 pub(crate) cache: RefCell<Option<bool>>,
273 pub(crate) raw_cache: RefCell<Option<Vec<u8>>>,
274}
275
276#[derive(Debug)]
281pub struct SkNode {
282 pub name: String,
284 pub meta: NodeMeta,
286 pub output: SkOutput,
288 pub ast: AstNode,
290 pub vars: Vec<(String, String)>,
292 pub cache: RefCell<Option<(f64, u64)>>,
294}
295
296#[derive(Debug)]
298pub struct CommandNode {
299 pub name: String,
300 pub meta: NodeMeta,
302 pub address: Option<u64>,
304 pub len: u32,
305 pub pvalue: Option<String>,
307 pub command_value: Option<i64>,
309}
310
311#[derive(Debug)]
313pub struct CategoryNode {
314 pub name: String,
315 pub meta: NodeMeta,
317 pub children: Vec<String>,
318}
319
320#[derive(Debug)]
326pub struct ConverterNode {
327 pub name: String,
329 pub meta: NodeMeta,
331 pub p_value: String,
333 pub ast_to: AstNode,
335 pub ast_from: AstNode,
337 pub vars_to: Vec<(String, String)>,
339 pub vars_from: Vec<(String, String)>,
341 pub unit: Option<String>,
343 pub output: SkOutput,
345 pub cache: RefCell<Option<(f64, u64)>>,
347}
348
349#[derive(Debug)]
351pub struct IntConverterNode {
352 pub name: String,
354 pub meta: NodeMeta,
356 pub p_value: String,
358 pub ast_to: AstNode,
360 pub ast_from: AstNode,
362 pub vars_to: Vec<(String, String)>,
364 pub vars_from: Vec<(String, String)>,
366 pub unit: Option<String>,
368 pub cache: RefCell<Option<(i64, u64)>>,
370}
371
372#[derive(Debug)]
374pub struct StringNode {
375 pub name: String,
377 pub meta: NodeMeta,
379 pub addressing: Addressing,
381 pub access: AccessMode,
383 pub cache: RefCell<Option<(String, u64)>>,
385}