1use std::cell::Cell;
4use std::collections::{HashMap, HashSet, hash_map::Entry as HashMapEntry};
5
6use tracing::{debug, trace, warn};
7use viva_genapi_xml::{
8 AccessMode, AddressTerm, Addressing, ByteOrder, EnumEntryDecl, EnumValueSrc, FloatEncoding,
9 FormulaBindings, IndexOffset, NodeDecl, PredicateRefs, Sign, SkippedNode, Visibility, XmlModel,
10};
11
12use crate::bitops::{extract, insert};
13use crate::conversions::{
14 apply_scale, bytes_to_i64, decode_ieee754, encode_bitfield_value, encode_float, encode_ieee754,
15 get_raw_or_read, i64_to_bytes, interpret_bitfield_value, map_bitops_error, round_to_i64,
16};
17use crate::nodes::{
18 BooleanNode, CategoryNode, CommandNode, ConverterNode, EnumMapping, EnumNode, FloatNode,
19 IntConverterNode, IntegerNode, Node, RegisterNode, SkNode, StringNode,
20};
21use crate::swissknife::{
22 AstNode as SkAst, EvalError as SkEvalError, EvalMode, Value as SkValue, collect_identifiers,
23 evaluate as eval_ast, is_builtin_constant, parse_expression, substitute,
24};
25use crate::{GenApiError, RegisterIo, SkOutput};
26
27#[derive(Debug)]
30pub struct NodeMap {
31 version: String,
32 nodes: HashMap<String, Node>,
33 dependents: HashMap<String, Vec<String>>,
34 skipped: Vec<SkippedNode>,
35 generation: Cell<u64>,
36}
37
38fn register_addressing_dependency(
39 dependents: &mut HashMap<String, Vec<String>>,
40 node_name: &str,
41 addressing: &Addressing,
42) {
43 for provider in addressing.referenced_nodes() {
44 dependents
45 .entry(provider.to_string())
46 .or_default()
47 .push(node_name.to_string());
48 }
49}
50
51fn register_predicate_dependencies(
52 dependents: &mut HashMap<String, Vec<String>>,
53 node_name: &str,
54 predicates: &PredicateRefs,
55) {
56 for provider in predicates.references() {
57 dependents
58 .entry(provider.to_string())
59 .or_default()
60 .push(node_name.to_string());
61 }
62}
63
64fn ensure_readable(access: &AccessMode, name: &str) -> Result<(), GenApiError> {
65 if matches!(access, AccessMode::WO) {
66 return Err(GenApiError::Access(name.to_string()));
67 }
68 Ok(())
69}
70
71fn ensure_device_port(name: &str, port: Option<&str>) -> Result<(), GenApiError> {
89 match port {
90 None => Ok(()),
91 Some(p) if p.eq_ignore_ascii_case("Device") => Ok(()),
92 Some(p) => Err(GenApiError::Unavailable(format!(
93 "register '{name}' is bound to port '{p}'; \
94 non-device ports are not routed yet (GA-12)"
95 ))),
96 }
97}
98
99fn ensure_writable(access: &AccessMode, name: &str) -> Result<(), GenApiError> {
100 if matches!(access, AccessMode::RO) {
101 return Err(GenApiError::Access(name.to_string()));
102 }
103 Ok(())
104}
105
106impl NodeMap {
107 pub fn version(&self) -> &str {
109 &self.version
110 }
111
112 pub fn node(&self, name: &str) -> Option<&Node> {
114 self.nodes.get(name)
115 }
116
117 pub fn node_names(&self) -> impl Iterator<Item = &str> {
119 self.nodes.keys().map(|s| s.as_str())
120 }
121
122 pub fn dependents(&self, name: &str) -> &[String] {
126 self.dependents
127 .get(name)
128 .map(|v| v.as_slice())
129 .unwrap_or(&[])
130 }
131
132 pub fn categories(&self) -> Vec<(&str, &[String])> {
134 self.nodes
135 .values()
136 .filter_map(|node| match node {
137 Node::Category(cat) => Some((cat.name.as_str(), cat.children.as_slice())),
138 _ => None,
139 })
140 .collect()
141 }
142
143 pub fn nodes_at_visibility(&self, level: Visibility) -> Vec<&str> {
148 self.nodes
149 .iter()
150 .filter(|(_, node)| node.visibility() <= level)
151 .map(|(name, _)| name.as_str())
152 .collect()
153 }
154
155 pub fn try_from_xml(model: XmlModel) -> Result<Self, GenApiError> {
163 let mut nodes = HashMap::new();
164 let mut dependents: HashMap<String, Vec<String>> = HashMap::new();
165 let mut skipped = model.skipped;
170 for decl in model.nodes {
171 let tag = decl.kind().to_string();
172 let name = Some(decl.name().to_string());
173 let mut local: HashMap<String, Vec<String>> = HashMap::new();
177 match build_node(decl, &mut local) {
178 Ok((node_name, node)) => {
179 for (provider, mut names) in local {
180 dependents.entry(provider).or_default().append(&mut names);
181 }
182 nodes.insert(node_name, node);
183 }
184 Err(err) => {
185 warn!(
186 tag = %tag,
187 node = name.as_deref().unwrap_or("<unnamed>"),
188 error = %err,
189 "dropping GenApi node"
190 );
191 skipped.push(SkippedNode {
192 tag,
193 name,
194 error: err.to_string(),
195 });
196 }
197 }
198 }
199
200 Ok(NodeMap {
201 version: model.version,
202 nodes,
203 dependents,
204 skipped,
205 generation: Cell::new(0),
206 })
207 }
208
209 pub fn skipped(&self) -> &[SkippedNode] {
216 &self.skipped
217 }
218
219 pub fn get_integer(&self, name: &str, io: &dyn RegisterIo) -> Result<i64, GenApiError> {
221 if let Some(Node::IntConverter(_)) = self.nodes.get(name) {
222 return self.get_int_converter(name, io);
223 }
224 if let Some(output) = self.nodes.get(name).and_then(|node| match node {
225 Node::SwissKnife(sk) => Some(sk.output),
226 _ => None,
227 }) {
228 return match output {
229 SkOutput::Integer => {
230 let node = match self.nodes.get(name) {
231 Some(Node::SwissKnife(node)) => node,
232 _ => unreachable!("node vanished during lookup"),
233 };
234 let mut stack = HashSet::new();
235 let value = self.evaluate_swissknife(node, io, &mut stack)?;
236 sk_to_i64(name, value)
237 }
238 SkOutput::Float => Err(GenApiError::Type(name.to_string())),
239 };
240 }
241 let node = self.get_integer_node(name)?;
242 ensure_readable(&node.access, name)?;
243 self.ensure_selectors(name, &node.selected_if, io)?;
244 if let Some(v) = node.value {
246 return Ok(v);
247 }
248 if let Some(ref pv) = node.pvalue {
250 let pv = pv.clone();
251 return self.get_integer(&pv, io);
252 }
253 let addressing = node
254 .addressing
255 .as_ref()
256 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing or pValue")))?;
257 let (address, len) = self.resolve_address(name, addressing, io)?;
258 if let Some(value) = *node.cache.borrow() {
259 return Ok(value);
260 }
261 let raw = io.read(address, len as usize).map_err(|err| match err {
262 GenApiError::Io(_) => err,
263 other => other,
264 })?;
265 let value = if let Some(bitfield) = node.bitfield {
266 let extracted = extract(&raw, bitfield).map_err(|err| map_bitops_error(name, err))?;
267 interpret_bitfield_value(
268 name,
269 extracted,
270 bitfield.bit_length,
271 integer_sign(node).is_signed(),
272 )?
273 } else {
274 bytes_to_i64(name, &raw, integer_sign(node), node.byte_order)?
275 };
276 debug!(node = %name, raw = value, "read integer feature");
277 node.cache.replace(Some(value));
278 node.raw_cache.replace(Some(raw));
279 Ok(value)
280 }
281
282 pub fn set_integer(
284 &mut self,
285 name: &str,
286 value: i64,
287 io: &dyn RegisterIo,
288 ) -> Result<(), GenApiError> {
289 if let Some(Node::IntConverter(_)) = self.nodes.get(name) {
290 return self.set_int_converter(name, value, io);
291 }
292 let node = self.get_integer_node(name)?;
293 self.ensure_writable_now(name, &node.access, io)?;
294 self.ensure_selectors(name, &node.selected_if, io)?;
295 if let Some(ref pv) = node.pvalue {
296 let pv = pv.clone();
297 return self.set_integer(&pv, value, io);
298 }
299 let addressing = node
300 .addressing
301 .as_ref()
302 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing or pValue")))?;
303 let (address, len) = self.resolve_address(name, addressing, io)?;
304 if value < node.min || value > node.max {
305 return Err(GenApiError::Range(name.to_string()));
306 }
307 if let Some(inc) = node.inc
308 && inc != 0
309 && (value - node.min) % inc != 0
310 {
311 return Err(GenApiError::Range(name.to_string()));
312 }
313 if let Some(bitfield) = node.bitfield {
314 let encoded = encode_bitfield_value(name, value, bitfield.bit_length, node.min < 0)?;
315 let mut raw = get_raw_or_read(&node.raw_cache, io, address, len)?;
316 insert(&mut raw, bitfield, encoded).map_err(|err| map_bitops_error(name, err))?;
317 debug!(node = %name, raw = value, "write integer feature");
318 io.write(address, &raw).map_err(|err| match err {
319 GenApiError::Io(_) => err,
320 other => other,
321 })?;
322 node.cache.replace(Some(value));
323 node.raw_cache.replace(Some(raw));
324 } else {
325 let bytes = i64_to_bytes(name, value, len, integer_sign(node), node.byte_order)?;
326 debug!(node = %name, raw = value, "write integer feature");
327 io.write(address, &bytes).map_err(|err| match err {
328 GenApiError::Io(_) => err,
329 other => other,
330 })?;
331 node.cache.replace(Some(value));
332 node.raw_cache.replace(Some(bytes));
333 }
334 self.invalidate_dependents(name);
335 Ok(())
336 }
337
338 pub fn get_float(&self, name: &str, io: &dyn RegisterIo) -> Result<f64, GenApiError> {
340 match self.nodes.get(name) {
341 Some(Node::Converter(_)) => return self.get_converter(name, io),
342 Some(Node::IntConverter(_)) => {
343 return self.get_int_converter(name, io).map(|v| v as f64);
344 }
345 _ => {}
346 }
347 if let Some(output) = self.nodes.get(name).and_then(|node| match node {
348 Node::SwissKnife(sk) => Some(sk.output),
349 _ => None,
350 }) {
351 return match output {
352 SkOutput::Float => {
353 let node = match self.nodes.get(name) {
354 Some(Node::SwissKnife(node)) => node,
355 _ => unreachable!("node vanished during lookup"),
356 };
357 let mut stack = HashSet::new();
358 let value = self.evaluate_swissknife(node, io, &mut stack)?;
359 Ok(value.as_f64())
360 }
361 SkOutput::Integer => self.get_integer(name, io).map(|v| v as f64),
362 };
363 }
364 let node = self.get_float_node(name)?;
365 ensure_readable(&node.access, name)?;
366 self.ensure_selectors(name, &node.selected_if, io)?;
367 if let Some(ref pv) = node.pvalue {
368 let pv = pv.clone();
369 return self.get_float(&pv, io);
370 }
371 let addressing = node
372 .addressing
373 .as_ref()
374 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing or pValue")))?;
375 let (address, len) = self.resolve_address(name, addressing, io)?;
376 if let Some(value) = *node.cache.borrow() {
377 return Ok(value);
378 }
379 let raw = io.read(address, len as usize).map_err(|err| match err {
380 GenApiError::Io(_) => err,
381 other => other,
382 })?;
383 let value = match node.encoding {
384 FloatEncoding::Ieee754 => {
385 let v = decode_ieee754(name, &raw, node.byte_order)?;
386 debug!(node = %name, value = v, "read float feature (ieee754)");
387 v
388 }
389 FloatEncoding::ScaledInteger => {
390 let raw_value = bytes_to_i64(name, &raw, Sign::Signed, node.byte_order)?;
393 let v = apply_scale(node, raw_value as f64);
394 debug!(node = %name, raw = raw_value, value = v, "read float feature (scaled)");
395 v
396 }
397 };
398 node.cache.replace(Some(value));
399 Ok(value)
400 }
401
402 pub fn set_float(
404 &mut self,
405 name: &str,
406 value: f64,
407 io: &dyn RegisterIo,
408 ) -> Result<(), GenApiError> {
409 match self.nodes.get(name) {
410 Some(Node::Converter(_)) => return self.set_converter(name, value, io),
411 Some(Node::IntConverter(_)) => {
412 return self.set_int_converter(name, round_to_i64(name, value)?, io);
413 }
414 _ => {}
415 }
416 let node = self.get_float_node(name)?;
417 self.ensure_writable_now(name, &node.access, io)?;
418 self.ensure_selectors(name, &node.selected_if, io)?;
419 if let Some(ref pv) = node.pvalue {
420 let pv = pv.clone();
421 return self.set_float(&pv, value, io);
422 }
423 let addressing = node
424 .addressing
425 .as_ref()
426 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing or pValue")))?;
427 let (address, len) = self.resolve_address(name, addressing, io)?;
428 if value < node.min || value > node.max {
429 return Err(GenApiError::Range(name.to_string()));
430 }
431 let bytes = match node.encoding {
432 FloatEncoding::Ieee754 => {
433 let bytes = encode_ieee754(name, value, len, node.byte_order)?;
434 debug!(node = %name, value, "write float feature (ieee754)");
435 bytes
436 }
437 FloatEncoding::ScaledInteger => {
438 let raw = encode_float(node, value)?;
439 let bytes = i64_to_bytes(name, raw, len, Sign::Signed, node.byte_order)?;
440 debug!(node = %name, raw, value, "write float feature (scaled)");
441 bytes
442 }
443 };
444 io.write(address, &bytes).map_err(|err| match err {
445 GenApiError::Io(_) => err,
446 other => other,
447 })?;
448 node.cache.replace(Some(value));
449 self.invalidate_dependents(name);
450 Ok(())
451 }
452
453 pub fn get_enum(&self, name: &str, io: &dyn RegisterIo) -> Result<String, GenApiError> {
455 let node = self.get_enum_node(name)?;
456 ensure_readable(&node.access, name)?;
457 self.ensure_selectors(name, &node.selected_if, io)?;
458 if let Some(ref pv) = node.pvalue {
460 let pv = pv.clone();
461 if let Some(value) = node.value_cache.borrow().clone() {
462 return Ok(value);
463 }
464 let raw_value = self.get_integer(&pv, io)?;
465 let entry = self.lookup_enum_entry(node, raw_value, io)?;
466 node.value_cache.replace(Some(entry.clone()));
467 return Ok(entry);
468 }
469 let addressing = node
470 .addressing
471 .as_ref()
472 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing")))?;
473 let (address, len) = self.resolve_address(name, addressing, io)?;
474 if let Some(value) = node.value_cache.borrow().clone() {
475 return Ok(value);
476 }
477 let raw = io.read(address, len as usize).map_err(|err| match err {
478 GenApiError::Io(_) => err,
479 other => other,
480 })?;
481 let raw_value = bytes_to_i64(name, &raw, Sign::Signed, ByteOrder::Big)?;
485 let entry = self.lookup_enum_entry(node, raw_value, io)?;
486 debug!(node = %name, raw = raw_value, entry = %entry, "read enum feature");
487 node.value_cache.replace(Some(entry.clone()));
488 Ok(entry)
489 }
490
491 pub fn set_enum(
493 &mut self,
494 name: &str,
495 entry: &str,
496 io: &dyn RegisterIo,
497 ) -> Result<(), GenApiError> {
498 let node = self.get_enum_node(name)?;
499 self.ensure_writable_now(name, &node.access, io)?;
500 self.ensure_selectors(name, &node.selected_if, io)?;
501 if let Some(ref pv) = node.pvalue {
502 let pv = pv.clone();
503 let entry_decl = node
504 .entries
505 .iter()
506 .find(|candidate| candidate.name == entry)
507 .ok_or_else(|| GenApiError::EnumNoSuchEntry {
508 node: name.to_string(),
509 entry: entry.to_string(),
510 })?;
511 let raw_value = self.resolve_enum_entry_value(node, entry_decl, io)?;
512 let entry_str = entry.to_string();
513 self.set_integer(&pv, raw_value, io)?;
515 let node = self.get_enum_node(name)?;
516 node.value_cache.replace(Some(entry_str));
517 node.invalidate();
518 self.invalidate_dependents(name);
519 return Ok(());
520 }
521 let addressing = node
522 .addressing
523 .as_ref()
524 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing")))?;
525 let (address, len) = self.resolve_address(name, addressing, io)?;
526 let entry_decl = node
527 .entries
528 .iter()
529 .find(|candidate| candidate.name == entry)
530 .ok_or_else(|| GenApiError::EnumNoSuchEntry {
531 node: name.to_string(),
532 entry: entry.to_string(),
533 })?;
534 let raw = self.resolve_enum_entry_value(node, entry_decl, io)?;
535 let bytes = i64_to_bytes(name, raw, len, Sign::Signed, ByteOrder::Big)?;
536 debug!(node = %name, raw, entry, "write enum feature");
537 io.write(address, &bytes).map_err(|err| match err {
538 GenApiError::Io(_) => err,
539 other => other,
540 })?;
541 node.value_cache.replace(None);
542 self.invalidate_dependents(name);
543 Ok(())
544 }
545
546 pub fn enum_entries(&self, name: &str) -> Result<Vec<String>, GenApiError> {
548 let node = self.get_enum_node(name)?;
549 if let Some(mapping) = node.mapping_cache.borrow().as_ref() {
550 let mut names: Vec<_> = mapping.by_name.keys().cloned().collect();
551 names.sort();
552 names.dedup();
553 return Ok(names);
554 }
555 let mut names: Vec<_> = node
556 .entries
557 .iter()
558 .map(|entry| entry.name.clone())
559 .collect();
560 names.sort();
561 names.dedup();
562 Ok(names)
563 }
564
565 pub fn is_implemented(&self, name: &str, io: &dyn RegisterIo) -> Result<bool, GenApiError> {
573 let prefs = self.predicate_refs(name)?;
574 match &prefs.p_is_implemented {
575 None => Ok(true),
576 Some(provider) => self.eval_predicate_ref(name, provider, io),
577 }
578 }
579
580 pub fn is_available(&self, name: &str, io: &dyn RegisterIo) -> Result<bool, GenApiError> {
588 if !self.is_implemented(name, io)? {
589 return Ok(false);
590 }
591 let prefs = self.predicate_refs(name)?;
592 if let Some(provider) = &prefs.p_is_available
593 && !self.eval_predicate_ref(name, provider, io)?
594 {
595 return Ok(false);
596 }
597 let selected_if = self
598 .nodes
599 .get(name)
600 .and_then(Self::selected_if_slice)
601 .unwrap_or(&[]);
602 self.selectors_allow(selected_if, io)
603 }
604
605 fn ensure_writable_now(
626 &self,
627 name: &str,
628 access: &AccessMode,
629 io: &dyn RegisterIo,
630 ) -> Result<(), GenApiError> {
631 ensure_writable(access, name)?;
632 if !self.is_available(name, io)? {
633 return Err(GenApiError::Unavailable(name.to_string()));
634 }
635 let prefs = self.predicate_refs(name)?;
636 if let Some(provider) = &prefs.p_is_locked
637 && self.eval_predicate_ref(name, provider, io)?
638 {
639 return Err(GenApiError::Locked {
640 name: name.to_string(),
641 locked_by: provider.to_string(),
642 });
643 }
644 Ok(())
645 }
646
647 pub fn effective_access_mode(
658 &self,
659 name: &str,
660 io: &dyn RegisterIo,
661 ) -> Result<AccessMode, GenApiError> {
662 let node = self
663 .nodes
664 .get(name)
665 .ok_or_else(|| GenApiError::NodeNotFound(name.to_string()))?;
666 let base = node.access_mode().unwrap_or(AccessMode::RO);
667 if !self.is_available(name, io)? {
668 return Ok(AccessMode::RO);
669 }
670 let prefs = self.predicate_refs(name)?;
671 if let Some(provider) = &prefs.p_is_locked
672 && self.eval_predicate_ref(name, provider, io)?
673 {
674 return Ok(match base {
675 AccessMode::RW => AccessMode::RO,
676 other => other,
677 });
678 }
679 Ok(base)
680 }
681
682 pub fn available_enum_entries(
691 &self,
692 name: &str,
693 io: &dyn RegisterIo,
694 ) -> Result<Vec<String>, GenApiError> {
695 let node = self.get_enum_node(name)?;
696 let any_entry_predicate = node.entries.iter().any(|e| !e.predicates.is_empty());
697 if !any_entry_predicate {
698 return self.enum_entries(name);
699 }
700 let mut out = Vec::new();
701 for entry in &node.entries {
702 if let Some(provider) = &entry.predicates.p_is_implemented
703 && !self.eval_predicate_ref(name, provider, io)?
704 {
705 continue;
706 }
707 if let Some(provider) = &entry.predicates.p_is_available
708 && !self.eval_predicate_ref(name, provider, io)?
709 {
710 continue;
711 }
712 out.push(entry.name.clone());
713 }
714 out.sort();
715 out.dedup();
716 Ok(out)
717 }
718
719 fn predicate_refs(&self, name: &str) -> Result<&PredicateRefs, GenApiError> {
720 self.nodes
721 .get(name)
722 .map(Node::predicates)
723 .ok_or_else(|| GenApiError::NodeNotFound(name.to_string()))
724 }
725
726 fn eval_predicate_ref(
735 &self,
736 ctx: &str,
737 provider: &str,
738 io: &dyn RegisterIo,
739 ) -> Result<bool, GenApiError> {
740 if provider == ctx {
741 return Err(GenApiError::ExprEval {
742 name: ctx.to_string(),
743 msg: "predicate references the node it gates".into(),
744 });
745 }
746 let mut stack = HashSet::new();
747 stack.insert(ctx.to_string());
748 let value = self.resolve_numeric(provider, io, &mut stack)?;
749 trace!(node = %ctx, provider, value, "predicate eval");
750 Ok(value != 0.0)
751 }
752
753 fn selectors_allow(
757 &self,
758 rules: &[(String, Vec<String>)],
759 io: &dyn RegisterIo,
760 ) -> Result<bool, GenApiError> {
761 for (selector, allowed) in rules {
762 if allowed.is_empty() {
763 continue;
764 }
765 let current = self.get_selector_value(selector, io)?;
766 if !allowed.iter().any(|v| v == ¤t) {
767 return Ok(false);
768 }
769 }
770 Ok(true)
771 }
772
773 fn selected_if_slice(node: &Node) -> Option<&[(String, Vec<String>)]> {
774 match node {
775 Node::Integer(n) => Some(&n.selected_if),
776 Node::Float(n) => Some(&n.selected_if),
777 Node::Enum(n) => Some(&n.selected_if),
778 Node::Boolean(n) => Some(&n.selected_if),
779 _ => None,
780 }
781 }
782
783 pub fn get_bool(&self, name: &str, io: &dyn RegisterIo) -> Result<bool, GenApiError> {
785 let node = self.get_bool_node(name)?;
786 ensure_readable(&node.access, name)?;
787 self.ensure_selectors(name, &node.selected_if, io)?;
788 if let Some(ref pv) = node.pvalue {
789 let pv = pv.clone();
790 let raw = self.get_integer(&pv, io)?;
791 let on = node.on_value.unwrap_or(1);
792 return Ok(raw == on);
793 }
794 let addressing = node
795 .addressing
796 .as_ref()
797 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing or pValue")))?;
798 let bitfield = node
799 .bitfield
800 .ok_or_else(|| GenApiError::Parse(format!("{name}: boolean without bitfield")))?;
801 let (address, len) = self.resolve_address(name, addressing, io)?;
802 if let Some(value) = *node.cache.borrow() {
803 return Ok(value);
804 }
805 let raw = io.read(address, len as usize).map_err(|err| match err {
806 GenApiError::Io(_) => err,
807 other => other,
808 })?;
809 let raw_value = extract(&raw, bitfield).map_err(|err| map_bitops_error(name, err))?;
810 let value = raw_value != 0;
811 debug!(node = %name, raw = raw_value, value, "read boolean feature");
812 node.cache.replace(Some(value));
813 node.raw_cache.replace(Some(raw));
814 Ok(value)
815 }
816
817 pub fn set_bool(
819 &mut self,
820 name: &str,
821 value: bool,
822 io: &dyn RegisterIo,
823 ) -> Result<(), GenApiError> {
824 let node = self.get_bool_node(name)?;
825 self.ensure_writable_now(name, &node.access, io)?;
826 self.ensure_selectors(name, &node.selected_if, io)?;
827 if let Some(ref pv) = node.pvalue {
828 let pv = pv.clone();
829 let on = node.on_value.unwrap_or(1);
830 let off = node.off_value.unwrap_or(0);
831 let raw = if value { on } else { off };
832 return self.set_integer(&pv, raw, io);
833 }
834 let addressing = node
835 .addressing
836 .as_ref()
837 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no addressing or pValue")))?;
838 let bitfield = node
839 .bitfield
840 .ok_or_else(|| GenApiError::Parse(format!("{name}: boolean without bitfield")))?;
841 let (address, len) = self.resolve_address(name, addressing, io)?;
842 let encoded = if value { 1 } else { 0 };
843 let mut raw = get_raw_or_read(&node.raw_cache, io, address, len)?;
844 insert(&mut raw, bitfield, encoded).map_err(|err| map_bitops_error(name, err))?;
845 debug!(node = %name, raw = encoded, value, "write boolean feature");
846 io.write(address, &raw).map_err(|err| match err {
847 GenApiError::Io(_) => err,
848 other => other,
849 })?;
850 node.cache.replace(Some(value));
851 node.raw_cache.replace(Some(raw));
852 self.invalidate_dependents(name);
853 Ok(())
854 }
855
856 pub fn exec_command(&mut self, name: &str, io: &dyn RegisterIo) -> Result<(), GenApiError> {
858 let node = self.get_command_node(name)?;
859 let cmd_value = node.command_value.unwrap_or(1);
861
862 if let Some(ref pv) = node.pvalue {
863 let pv = pv.clone();
865 debug!(node = %name, "execute command via pValue");
866 return self.set_integer(&pv, cmd_value, io);
867 }
868
869 let address = node
870 .address
871 .ok_or_else(|| GenApiError::NodeNotFound(format!("{name}: no address or pValue")))?;
872 if node.len == 0 {
873 return Err(GenApiError::Parse(format!(
874 "command node {name} has zero length"
875 )));
876 }
877 let data = i64_to_bytes(name, cmd_value, node.len, Sign::Signed, ByteOrder::Big)?;
878 debug!(node = %name, "execute command");
879 io.write(address, &data).map_err(|err| match err {
880 GenApiError::Io(_) => err,
881 other => other,
882 })?;
883 self.invalidate_dependents(name);
884 Ok(())
885 }
886
887 fn get_integer_node(&self, name: &str) -> Result<&IntegerNode, GenApiError> {
888 match self.nodes.get(name) {
889 Some(Node::Integer(node)) => Ok(node),
890 Some(_) => Err(GenApiError::Type(name.to_string())),
891 None => Err(GenApiError::NodeNotFound(name.to_string())),
892 }
893 }
894
895 fn get_float_node(&self, name: &str) -> Result<&FloatNode, GenApiError> {
896 match self.nodes.get(name) {
897 Some(Node::Float(node)) => Ok(node),
898 Some(_) => Err(GenApiError::Type(name.to_string())),
899 None => Err(GenApiError::NodeNotFound(name.to_string())),
900 }
901 }
902
903 fn get_enum_node(&self, name: &str) -> Result<&EnumNode, GenApiError> {
904 match self.nodes.get(name) {
905 Some(Node::Enum(node)) => Ok(node),
906 Some(_) => Err(GenApiError::Type(name.to_string())),
907 None => Err(GenApiError::NodeNotFound(name.to_string())),
908 }
909 }
910
911 fn get_bool_node(&self, name: &str) -> Result<&BooleanNode, GenApiError> {
912 match self.nodes.get(name) {
913 Some(Node::Boolean(node)) => Ok(node),
914 Some(_) => Err(GenApiError::Type(name.to_string())),
915 None => Err(GenApiError::NodeNotFound(name.to_string())),
916 }
917 }
918
919 fn get_command_node(&self, name: &str) -> Result<&CommandNode, GenApiError> {
920 match self.nodes.get(name) {
921 Some(Node::Command(node)) => Ok(node),
922 Some(_) => Err(GenApiError::Type(name.to_string())),
923 None => Err(GenApiError::NodeNotFound(name.to_string())),
924 }
925 }
926
927 fn ensure_selectors(
928 &self,
929 node_name: &str,
930 rules: &[(String, Vec<String>)],
931 io: &dyn RegisterIo,
932 ) -> Result<(), GenApiError> {
933 for (selector, allowed) in rules {
934 if allowed.is_empty() {
935 continue;
936 }
937 let current = self.get_selector_value(selector, io)?;
938 if !allowed.iter().any(|value| value == ¤t) {
939 return Err(GenApiError::Unavailable(format!(
940 "node '{node_name}' unavailable for selector '{selector}={current}'"
941 )));
942 }
943 }
944 Ok(())
945 }
946
947 fn lookup_enum_entry(
948 &self,
949 node: &EnumNode,
950 raw_value: i64,
951 io: &dyn RegisterIo,
952 ) -> Result<String, GenApiError> {
953 {
954 let mut cache = node.mapping_cache.borrow_mut();
955 if cache.is_none() {
956 *cache = Some(self.build_enum_mapping(node, io)?);
957 }
958 if let Some(mapping) = cache.as_ref()
959 && let Some(entry) = mapping.by_value.get(&raw_value)
960 {
961 return Ok(entry.clone());
962 }
963 *cache = Some(self.build_enum_mapping(node, io)?);
964 if let Some(mapping) = cache.as_ref()
965 && let Some(entry) = mapping.by_value.get(&raw_value)
966 {
967 return Ok(entry.clone());
968 }
969 }
970 Err(GenApiError::EnumValueUnknown {
971 node: node.name.clone(),
972 value: raw_value,
973 })
974 }
975
976 fn build_enum_mapping(
977 &self,
978 node: &EnumNode,
979 io: &dyn RegisterIo,
980 ) -> Result<EnumMapping, GenApiError> {
981 let mut by_value = HashMap::new();
982 let mut by_name = HashMap::new();
983
984 for entry in &node.entries {
985 let value = self.resolve_enum_entry_value(node, entry, io)?;
986 match by_value.entry(value) {
987 HashMapEntry::Vacant(slot) => {
988 slot.insert(entry.name.clone());
989 }
990 HashMapEntry::Occupied(existing) => {
991 warn!(
992 enum_node = %node.name,
993 value,
994 kept = %existing.get(),
995 dropped = %entry.name,
996 "duplicate enum value"
997 );
998 }
999 }
1000 by_name.insert(entry.name.clone(), value);
1001 }
1002
1003 let mut summary: Vec<_> = by_value
1004 .iter()
1005 .map(|(value, name)| (*value, name.clone()))
1006 .collect();
1007 summary.sort_by_key(|(value, _)| *value);
1008 debug!(node = %node.name, entries = ?summary, "build enum mapping");
1009
1010 Ok(EnumMapping { by_value, by_name })
1011 }
1012
1013 fn resolve_enum_entry_value(
1014 &self,
1015 node: &EnumNode,
1016 entry: &EnumEntryDecl,
1017 io: &dyn RegisterIo,
1018 ) -> Result<i64, GenApiError> {
1019 match &entry.value {
1020 EnumValueSrc::Literal(value) => Ok(*value),
1021 EnumValueSrc::FromNode(provider) => {
1022 let value = self.get_integer(provider, io)?;
1023 trace!(
1024 enum_node = %node.name,
1025 entry = %entry.name,
1026 provider = %provider,
1027 value,
1028 "resolved enum entry from provider"
1029 );
1030 Ok(value)
1031 }
1032 }
1033 }
1034
1035 pub fn register_address(
1049 &self,
1050 name: &str,
1051 io: &dyn RegisterIo,
1052 ) -> Result<(u64, u32), GenApiError> {
1053 let node = self
1054 .node(name)
1055 .ok_or_else(|| GenApiError::NodeNotFound(name.to_string()))?;
1056 let addressing = match node {
1057 Node::Integer(node) => node.addressing.as_ref(),
1058 Node::Float(node) => node.addressing.as_ref(),
1059 Node::Enum(node) => node.addressing.as_ref(),
1060 Node::Boolean(node) => node.addressing.as_ref(),
1061 Node::String(node) => Some(&node.addressing),
1062 Node::Register(node) => Some(&node.addressing),
1063 _ => None,
1064 }
1065 .ok_or_else(|| {
1066 GenApiError::Unavailable(format!("node '{name}' has no register addressing"))
1067 })?;
1068 self.resolve_address(name, addressing, io)
1069 }
1070
1071 fn resolve_address(
1072 &self,
1073 node_name: &str,
1074 addressing: &Addressing,
1075 io: &dyn RegisterIo,
1076 ) -> Result<(u64, u32), GenApiError> {
1077 match addressing {
1078 Addressing::Sum { terms, len } => {
1079 let mut address: u64 = 0;
1080 for term in terms {
1081 address =
1082 address.wrapping_add(self.resolve_address_term(node_name, term, *len, io)?);
1083 }
1084 if terms.len() > 1 {
1085 debug!(
1086 node = %node_name,
1087 terms = terms.len(),
1088 address = format_args!("0x{address:X}"),
1089 len = *len,
1090 "resolve summed address"
1091 );
1092 }
1093 Ok((address, *len))
1094 }
1095 Addressing::BySelector { selector, map } => {
1096 let value = self.get_selector_value(selector, io)?;
1097 if let Some((_, (address, len))) = map.iter().find(|(name, _)| name == &value) {
1098 let addr = *address;
1099 let len = *len;
1100 debug!(
1101 node = %node_name,
1102 selector = %selector,
1103 value = %value,
1104 address = format_args!("0x{addr:X}"),
1105 len,
1106 "resolve address via selector"
1107 );
1108 Ok((addr, len))
1109 } else {
1110 Err(GenApiError::Unavailable(format!(
1111 "node '{node_name}' unavailable for selector '{selector}={value}'"
1112 )))
1113 }
1114 }
1115 }
1116 }
1117
1118 fn resolve_address_term(
1120 &self,
1121 node_name: &str,
1122 term: &AddressTerm,
1123 len: u32,
1124 io: &dyn RegisterIo,
1125 ) -> Result<u64, GenApiError> {
1126 let bad = |addr: i64| GenApiError::BadIndirectAddress {
1127 name: node_name.to_string(),
1128 addr,
1129 };
1130 match term {
1131 AddressTerm::Fixed(offset) => Ok(*offset),
1132 AddressTerm::Node(provider) => {
1133 let value = self.get_integer(provider, io)?;
1134 u64::try_from(value).map_err(|_| bad(value))
1135 }
1136 AddressTerm::Index { node, offset } => {
1137 let index = self.get_integer(node, io)?;
1138 let index = u64::try_from(index).map_err(|_| bad(index))?;
1139 let stride = match offset {
1140 IndexOffset::Fixed(stride) => *stride,
1141 IndexOffset::Node(provider) => {
1142 let value = self.get_integer(provider, io)?;
1143 u64::try_from(value).map_err(|_| bad(value))?
1144 }
1145 IndexOffset::Length => u64::from(len),
1147 };
1148 Ok(index.wrapping_mul(stride))
1149 }
1150 }
1151 }
1152
1153 fn get_selector_value(
1154 &self,
1155 selector: &str,
1156 io: &dyn RegisterIo,
1157 ) -> Result<String, GenApiError> {
1158 match self.nodes.get(selector) {
1159 Some(Node::Enum(_)) => self.get_enum(selector, io),
1160 Some(Node::Boolean(_)) => Ok(self.get_bool(selector, io)?.to_string()),
1161 Some(Node::Integer(_)) => Ok(self.get_integer(selector, io)?.to_string()),
1162 Some(_) => Err(GenApiError::Parse(format!(
1163 "selector {selector} has unsupported type"
1164 ))),
1165 None => Err(GenApiError::NodeNotFound(selector.to_string())),
1166 }
1167 }
1168
1169 #[allow(clippy::too_many_arguments)]
1176 fn eval_formula(
1177 &self,
1178 name: &str,
1179 ast: &SkAst,
1180 vars: &[(String, String)],
1181 overrides: &[(&str, SkValue)],
1182 mode: EvalMode,
1183 io: &dyn RegisterIo,
1184 stack: &mut HashSet<String>,
1185 ) -> Result<SkValue, GenApiError> {
1186 let mut values: HashMap<String, SkValue> = HashMap::new();
1187 for (var, provider) in vars {
1188 if overrides.iter().any(|(ident, _)| ident == var) {
1189 continue;
1190 }
1191 values.insert(var.clone(), self.resolve_value(provider, io, stack)?);
1192 }
1193 for (ident, value) in overrides {
1194 values.insert((*ident).to_string(), *value);
1195 }
1196 let mut resolver = |ident: &str| -> Result<SkValue, SkEvalError> {
1197 values
1198 .get(ident)
1199 .copied()
1200 .ok_or_else(|| SkEvalError::UnknownVariable(ident.to_string()))
1201 };
1202 eval_ast(ast, &mut resolver, mode).map_err(|err| expr_error(name, err))
1203 }
1204
1205 fn evaluate_swissknife(
1206 &self,
1207 node: &SkNode,
1208 io: &dyn RegisterIo,
1209 stack: &mut HashSet<String>,
1210 ) -> Result<SkValue, GenApiError> {
1211 if let Some((value, generation)) = *node.cache.borrow()
1212 && generation == self.generation.get()
1213 {
1214 return Ok(value);
1215 }
1216 if !stack.insert(node.name.clone()) {
1217 stack.remove(&node.name);
1218 return Err(GenApiError::ExprEval {
1219 name: node.name.clone(),
1220 msg: "cyclic dependency".into(),
1221 });
1222 }
1223 let current_gen = self.generation.get();
1224 let result = self.eval_formula(
1225 &node.name,
1226 &node.ast,
1227 &node.vars,
1228 &[],
1229 eval_mode(node.output),
1230 io,
1231 stack,
1232 );
1233 stack.remove(&node.name);
1234 let value = result?;
1235 debug!(node = %node.name, value = %value, "evaluate SwissKnife");
1236 node.cache.replace(Some((value, current_gen)));
1237 Ok(value)
1238 }
1239
1240 fn resolve_value(
1245 &self,
1246 provider: &str,
1247 io: &dyn RegisterIo,
1248 stack: &mut HashSet<String>,
1249 ) -> Result<SkValue, GenApiError> {
1250 match self.nodes.get(provider) {
1251 Some(Node::Integer(_)) => self.get_integer(provider, io).map(SkValue::Int),
1252 Some(Node::Float(_)) => self.get_float(provider, io).map(SkValue::Float),
1253 Some(Node::Boolean(_)) => self
1254 .get_bool(provider, io)
1255 .map(|flag| SkValue::Int(i64::from(flag))),
1256 Some(Node::Enum(_)) => self.get_enum_numeric(provider, io).map(SkValue::Int),
1257 Some(Node::SwissKnife(node)) => self.evaluate_swissknife(node, io, stack),
1258 Some(Node::Converter(node)) => self.evaluate_converter(node, io, stack),
1259 Some(Node::IntConverter(node)) => self
1260 .evaluate_int_converter(node, io, stack)
1261 .map(SkValue::Int),
1262 Some(_) => Err(GenApiError::Type(provider.to_string())),
1263 None => Err(GenApiError::NodeNotFound(provider.to_string())),
1264 }
1265 }
1266
1267 fn resolve_numeric(
1268 &self,
1269 provider: &str,
1270 io: &dyn RegisterIo,
1271 stack: &mut HashSet<String>,
1272 ) -> Result<f64, GenApiError> {
1273 self.resolve_value(provider, io, stack)
1274 .map(|value| value.as_f64())
1275 }
1276
1277 fn get_enum_numeric(&self, name: &str, io: &dyn RegisterIo) -> Result<i64, GenApiError> {
1278 let entry = self.get_enum(name, io)?;
1279 let node = self.get_enum_node(name)?;
1280 {
1281 let mut mapping = node.mapping_cache.borrow_mut();
1282 if mapping.is_none() {
1283 *mapping = Some(self.build_enum_mapping(node, io)?);
1284 }
1285 if let Some(map) = mapping.as_ref()
1286 && let Some(value) = map.by_name.get(&entry)
1287 {
1288 return Ok(*value);
1289 }
1290 }
1291 Err(GenApiError::EnumNoSuchEntry {
1292 node: name.to_string(),
1293 entry,
1294 })
1295 }
1296
1297 fn invalidate_dependents(&self, name: &str) {
1298 self.bump_generation();
1299 if let Some(children) = self.dependents.get(name) {
1300 let mut visited = HashSet::new();
1301 for child in children {
1302 self.invalidate_recursive(child, &mut visited);
1303 }
1304 }
1305 }
1306
1307 fn invalidate_recursive(&self, name: &str, visited: &mut HashSet<String>) {
1308 if !visited.insert(name.to_string()) {
1309 return;
1310 }
1311 if let Some(node) = self.nodes.get(name) {
1312 node.invalidate_cache();
1313 }
1314 if let Some(children) = self.dependents.get(name) {
1315 for child in children {
1316 self.invalidate_recursive(child, visited);
1317 }
1318 }
1319 }
1320
1321 fn bump_generation(&self) {
1322 let current = self.generation.get();
1323 self.generation.set(current.wrapping_add(1));
1324 }
1325
1326 fn get_converter_node(&self, name: &str) -> Result<&ConverterNode, GenApiError> {
1331 match self.nodes.get(name) {
1332 Some(Node::Converter(node)) => Ok(node),
1333 Some(_) => Err(GenApiError::Type(name.to_string())),
1334 None => Err(GenApiError::NodeNotFound(name.to_string())),
1335 }
1336 }
1337
1338 fn get_int_converter_node(&self, name: &str) -> Result<&IntConverterNode, GenApiError> {
1339 match self.nodes.get(name) {
1340 Some(Node::IntConverter(node)) => Ok(node),
1341 Some(_) => Err(GenApiError::Type(name.to_string())),
1342 None => Err(GenApiError::NodeNotFound(name.to_string())),
1343 }
1344 }
1345
1346 fn get_string_node(&self, name: &str) -> Result<&StringNode, GenApiError> {
1347 match self.nodes.get(name) {
1348 Some(Node::String(node)) => Ok(node),
1349 Some(_) => Err(GenApiError::Type(name.to_string())),
1350 None => Err(GenApiError::NodeNotFound(name.to_string())),
1351 }
1352 }
1353
1354 fn get_register_node(&self, name: &str) -> Result<&RegisterNode, GenApiError> {
1355 match self.nodes.get(name) {
1356 Some(Node::Register(node)) => Ok(node),
1357 Some(_) => Err(GenApiError::Type(name.to_string())),
1358 None => Err(GenApiError::NodeNotFound(name.to_string())),
1359 }
1360 }
1361
1362 pub fn get_converter(&self, name: &str, io: &dyn RegisterIo) -> Result<f64, GenApiError> {
1364 let node = self.get_converter_node(name)?;
1365 if let Some((value, generation)) = *node.cache.borrow()
1366 && generation == self.generation.get()
1367 {
1368 return Ok(value.as_f64());
1369 }
1370 let mut stack = HashSet::new();
1371 let value = self.evaluate_converter(node, io, &mut stack)?;
1372 node.cache.replace(Some((value, self.generation.get())));
1373 Ok(value.as_f64())
1374 }
1375
1376 pub fn get_int_converter(&self, name: &str, io: &dyn RegisterIo) -> Result<i64, GenApiError> {
1378 let node = self.get_int_converter_node(name)?;
1379 if let Some((value, generation)) = *node.cache.borrow()
1380 && generation == self.generation.get()
1381 {
1382 return Ok(value);
1383 }
1384 let mut stack = HashSet::new();
1385 let value = self.evaluate_int_converter(node, io, &mut stack)?;
1386 node.cache.replace(Some((value, self.generation.get())));
1387 Ok(value)
1388 }
1389
1390 pub fn set_converter(
1392 &mut self,
1393 name: &str,
1394 value: f64,
1395 io: &dyn RegisterIo,
1396 ) -> Result<(), GenApiError> {
1397 let node = self.get_converter_node(name)?;
1398 let (p_value, raw) = self.converter_raw_write(
1399 &node.name,
1400 &node.ast_to,
1401 &node.vars_to,
1402 &node.p_value,
1403 SkValue::Float(value),
1404 eval_mode(node.output),
1405 io,
1406 )?;
1407 self.write_converter_raw(&p_value, raw, io)?;
1408 self.invalidate_dependents(name);
1409 Ok(())
1410 }
1411
1412 pub fn set_int_converter(
1414 &mut self,
1415 name: &str,
1416 value: i64,
1417 io: &dyn RegisterIo,
1418 ) -> Result<(), GenApiError> {
1419 let node = self.get_int_converter_node(name)?;
1420 let (p_value, raw) = self.converter_raw_write(
1421 &node.name,
1422 &node.ast_to,
1423 &node.vars_to,
1424 &node.p_value,
1425 SkValue::Int(value),
1426 EvalMode::Integer,
1427 io,
1428 )?;
1429 self.write_converter_raw(&p_value, raw, io)?;
1430 self.invalidate_dependents(name);
1431 Ok(())
1432 }
1433
1434 #[allow(clippy::too_many_arguments)]
1441 fn converter_raw_write(
1442 &self,
1443 name: &str,
1444 ast_to: &SkAst,
1445 vars_to: &[(String, String)],
1446 p_value: &str,
1447 value: SkValue,
1448 mode: EvalMode,
1449 io: &dyn RegisterIo,
1450 ) -> Result<(String, SkValue), GenApiError> {
1451 let mut stack = HashSet::new();
1452 let mut overrides = vec![("FROM", value)];
1453 if vars_to.iter().any(|(var, _)| var == "OLD") {
1454 let old = self.resolve_value(p_value, io, &mut stack)?;
1455 overrides.push(("OLD", old));
1456 }
1457 let raw = self.eval_formula(name, ast_to, vars_to, &overrides, mode, io, &mut stack)?;
1458 Ok((p_value.to_string(), raw))
1459 }
1460
1461 fn write_converter_raw(
1462 &mut self,
1463 p_value: &str,
1464 raw: SkValue,
1465 io: &dyn RegisterIo,
1466 ) -> Result<(), GenApiError> {
1467 match self.nodes.get(p_value) {
1468 Some(Node::Float(_)) => self.set_float(p_value, raw.as_f64(), io),
1469 Some(Node::Boolean(_)) => self.set_bool(p_value, raw.is_truthy(), io),
1470 Some(_) => self.set_integer(p_value, sk_to_i64(p_value, raw)?, io),
1471 None => Err(GenApiError::NodeNotFound(p_value.to_string())),
1472 }
1473 }
1474
1475 pub fn get_string(&self, name: &str, io: &dyn RegisterIo) -> Result<String, GenApiError> {
1477 let node = self.get_string_node(name)?;
1478 ensure_readable(&node.access, name)?;
1479 if let Some((ref value, generation)) = *node.cache.borrow()
1480 && generation == self.generation.get()
1481 {
1482 return Ok(value.clone());
1483 }
1484 let (address, len) = self.resolve_address(name, &node.addressing, io)?;
1485 let raw = io.read(address, len as usize)?;
1486 let end = raw.iter().position(|&b| b == 0).unwrap_or(raw.len());
1488 let value = String::from_utf8_lossy(&raw[..end]).to_string();
1489 node.cache
1490 .replace(Some((value.clone(), self.generation.get())));
1491 debug!(node = %name, value = %value, "get_string");
1492 Ok(value)
1493 }
1494
1495 pub fn set_string(
1497 &self,
1498 name: &str,
1499 value: &str,
1500 io: &dyn RegisterIo,
1501 ) -> Result<(), GenApiError> {
1502 let node = self.get_string_node(name)?;
1503 self.ensure_writable_now(name, &node.access, io)?;
1504 let (address, len) = self.resolve_address(name, &node.addressing, io)?;
1505 let mut buf = vec![0u8; len as usize];
1507 let bytes = value.as_bytes();
1508 let copy_len = bytes.len().min(len as usize);
1509 buf[..copy_len].copy_from_slice(&bytes[..copy_len]);
1510 io.write(address, &buf)?;
1511 node.cache
1512 .replace(Some((value.to_string(), self.generation.get())));
1513 self.invalidate_dependents(name);
1514 debug!(node = %name, value = %value, "set_string");
1515 Ok(())
1516 }
1517
1518 pub fn get_register(&self, name: &str, io: &dyn RegisterIo) -> Result<Vec<u8>, GenApiError> {
1525 let node = self.get_register_node(name)?;
1526 ensure_readable(&node.access, name)?;
1527 ensure_device_port(name, node.port.as_deref())?;
1528 if let Some((ref value, generation)) = *node.cache.borrow()
1529 && generation == self.generation.get()
1530 {
1531 return Ok(value.clone());
1532 }
1533 let (address, len) = self.resolve_address(name, &node.addressing, io)?;
1534 let raw = io.read(address, len as usize)?;
1535 node.cache
1536 .replace(Some((raw.clone(), self.generation.get())));
1537 debug!(node = %name, len = raw.len(), "get_register");
1538 Ok(raw)
1539 }
1540
1541 pub fn set_register(
1548 &self,
1549 name: &str,
1550 data: &[u8],
1551 io: &dyn RegisterIo,
1552 ) -> Result<(), GenApiError> {
1553 let node = self.get_register_node(name)?;
1554 self.ensure_writable_now(name, &node.access, io)?;
1555 ensure_device_port(name, node.port.as_deref())?;
1556 let (address, len) = self.resolve_address(name, &node.addressing, io)?;
1557 if data.len() != len as usize {
1558 return Err(GenApiError::Range(format!(
1559 "register '{name}' is {len} bytes; got {}",
1560 data.len()
1561 )));
1562 }
1563 io.write(address, data)?;
1564 node.cache
1565 .replace(Some((data.to_vec(), self.generation.get())));
1566 self.invalidate_dependents(name);
1567 debug!(node = %name, len = data.len(), "set_register");
1568 Ok(())
1569 }
1570
1571 fn evaluate_converter(
1573 &self,
1574 node: &ConverterNode,
1575 io: &dyn RegisterIo,
1576 stack: &mut HashSet<String>,
1577 ) -> Result<SkValue, GenApiError> {
1578 if !stack.insert(node.name.clone()) {
1579 stack.remove(&node.name);
1580 return Err(GenApiError::ExprEval {
1581 name: node.name.clone(),
1582 msg: "cyclic dependency".into(),
1583 });
1584 }
1585 let result = self.eval_formula(
1586 &node.name,
1587 &node.ast_from,
1588 &node.vars_from,
1589 &[],
1590 eval_mode(node.output),
1591 io,
1592 stack,
1593 );
1594 stack.remove(&node.name);
1595 let value = result?;
1596 debug!(node = %node.name, value = %value, "evaluate Converter");
1597 Ok(value)
1598 }
1599
1600 fn evaluate_int_converter(
1602 &self,
1603 node: &IntConverterNode,
1604 io: &dyn RegisterIo,
1605 stack: &mut HashSet<String>,
1606 ) -> Result<i64, GenApiError> {
1607 if !stack.insert(node.name.clone()) {
1608 stack.remove(&node.name);
1609 return Err(GenApiError::ExprEval {
1610 name: node.name.clone(),
1611 msg: "cyclic dependency".into(),
1612 });
1613 }
1614 let result = self.eval_formula(
1615 &node.name,
1616 &node.ast_from,
1617 &node.vars_from,
1618 &[],
1619 EvalMode::Integer,
1620 io,
1621 stack,
1622 );
1623 stack.remove(&node.name);
1624 let int_value = result?.as_i64();
1625 debug!(node = %node.name, int_value, "evaluate IntConverter");
1626 Ok(int_value)
1627 }
1628}
1629
1630fn build_node(
1633 decl: NodeDecl,
1634 dependents: &mut HashMap<String, Vec<String>>,
1635) -> Result<(String, Node), GenApiError> {
1636 match decl {
1637 NodeDecl::Integer {
1638 name,
1639 meta,
1640 addressing,
1641 len,
1642 access,
1643 min,
1644 max,
1645 inc,
1646 unit,
1647 bitfield,
1648 sign,
1649 byte_order,
1650 selectors,
1651 selected_if,
1652 pvalue,
1653 p_max,
1654 p_min,
1655 value,
1656 predicates,
1657 } => {
1658 if let Some(ref addr) = addressing {
1659 register_addressing_dependency(dependents, &name, addr);
1660 }
1661 if let Some(ref pv) = pvalue {
1662 dependents.entry(pv.clone()).or_default().push(name.clone());
1663 }
1664 if let Some(ref pm) = p_max {
1665 dependents.entry(pm.clone()).or_default().push(name.clone());
1666 }
1667 if let Some(ref pm) = p_min {
1668 dependents.entry(pm.clone()).or_default().push(name.clone());
1669 }
1670 for (selector, _) in &selected_if {
1671 dependents
1672 .entry(selector.clone())
1673 .or_default()
1674 .push(name.clone());
1675 }
1676 register_predicate_dependencies(dependents, &name, &predicates);
1677 let node = IntegerNode {
1678 name: name.clone(),
1679 meta,
1680 addressing,
1681 len,
1682 access,
1683 min,
1684 max,
1685 inc,
1686 unit,
1687 bitfield,
1688 sign,
1689 byte_order,
1690 selectors,
1691 selected_if,
1692 pvalue,
1693 p_max,
1694 p_min,
1695 value,
1696 predicates,
1697 cache: std::cell::RefCell::new(None),
1698 raw_cache: std::cell::RefCell::new(None),
1699 };
1700 Ok((name, Node::Integer(node)))
1701 }
1702 NodeDecl::Float {
1703 name,
1704 meta,
1705 addressing,
1706 access,
1707 min,
1708 max,
1709 unit,
1710 scale,
1711 offset,
1712 selectors,
1713 selected_if,
1714 pvalue,
1715 encoding,
1716 byte_order,
1717 predicates,
1718 } => {
1719 if let Some(ref addr) = addressing {
1720 register_addressing_dependency(dependents, &name, addr);
1721 }
1722 if let Some(ref pv) = pvalue {
1723 dependents.entry(pv.clone()).or_default().push(name.clone());
1724 }
1725 for (selector, _) in &selected_if {
1726 dependents
1727 .entry(selector.clone())
1728 .or_default()
1729 .push(name.clone());
1730 }
1731 register_predicate_dependencies(dependents, &name, &predicates);
1732 let node = FloatNode {
1733 name: name.clone(),
1734 meta,
1735 addressing,
1736 access,
1737 min,
1738 max,
1739 unit,
1740 scale,
1741 offset,
1742 selectors,
1743 selected_if,
1744 pvalue,
1745 encoding,
1746 byte_order,
1747 predicates,
1748 cache: std::cell::RefCell::new(None),
1749 };
1750 Ok((name, Node::Float(node)))
1751 }
1752 NodeDecl::Enum {
1753 name,
1754 meta,
1755 addressing,
1756 access,
1757 entries,
1758 default,
1759 selectors,
1760 selected_if,
1761 pvalue,
1762 predicates,
1763 } => {
1764 if let Some(ref addr) = addressing {
1765 register_addressing_dependency(dependents, &name, addr);
1766 }
1767 if let Some(ref pv) = pvalue {
1768 dependents.entry(pv.clone()).or_default().push(name.clone());
1769 }
1770 for (selector, _) in &selected_if {
1771 dependents
1772 .entry(selector.clone())
1773 .or_default()
1774 .push(name.clone());
1775 }
1776 register_predicate_dependencies(dependents, &name, &predicates);
1777 let mut providers = Vec::new();
1778 let mut provider_set = HashSet::new();
1779 for entry in &entries {
1780 if let EnumValueSrc::FromNode(node_name) = &entry.value {
1781 dependents
1782 .entry(node_name.clone())
1783 .or_default()
1784 .push(name.clone());
1785 if provider_set.insert(node_name.clone()) {
1786 providers.push(node_name.clone());
1787 }
1788 }
1789 register_predicate_dependencies(dependents, &name, &entry.predicates);
1790 }
1791 providers.sort();
1792 let node = EnumNode {
1793 name: name.clone(),
1794 meta,
1795 addressing,
1796 access,
1797 pvalue,
1798 entries,
1799 default,
1800 selectors,
1801 selected_if,
1802 providers,
1803 predicates,
1804 value_cache: std::cell::RefCell::new(None),
1805 mapping_cache: std::cell::RefCell::new(None),
1806 };
1807 Ok((name, Node::Enum(node)))
1808 }
1809 NodeDecl::Boolean {
1810 name,
1811 meta,
1812 addressing,
1813 len,
1814 access,
1815 bitfield,
1816 selectors,
1817 selected_if,
1818 pvalue,
1819 on_value,
1820 off_value,
1821 predicates,
1822 } => {
1823 if let Some(ref addr) = addressing {
1824 register_addressing_dependency(dependents, &name, addr);
1825 }
1826 if let Some(ref pv) = pvalue {
1827 dependents.entry(pv.clone()).or_default().push(name.clone());
1828 }
1829 for (selector, _) in &selected_if {
1830 dependents
1831 .entry(selector.clone())
1832 .or_default()
1833 .push(name.clone());
1834 }
1835 register_predicate_dependencies(dependents, &name, &predicates);
1836 let node = BooleanNode {
1837 name: name.clone(),
1838 meta,
1839 addressing,
1840 len,
1841 access,
1842 bitfield,
1843 selectors,
1844 selected_if,
1845 pvalue,
1846 on_value,
1847 off_value,
1848 predicates,
1849 cache: std::cell::RefCell::new(None),
1850 raw_cache: std::cell::RefCell::new(None),
1851 };
1852 Ok((name, Node::Boolean(node)))
1853 }
1854 NodeDecl::Command {
1855 name,
1856 meta,
1857 address,
1858 len,
1859 pvalue,
1860 command_value,
1861 predicates,
1862 } => {
1863 if let Some(ref pv) = pvalue {
1864 dependents.entry(pv.clone()).or_default().push(name.clone());
1865 }
1866 register_predicate_dependencies(dependents, &name, &predicates);
1867 let node = CommandNode {
1868 name: name.clone(),
1869 meta,
1870 address,
1871 len,
1872 pvalue,
1873 command_value,
1874 predicates,
1875 };
1876 Ok((name, Node::Command(node)))
1877 }
1878 NodeDecl::Category {
1879 name,
1880 meta,
1881 children,
1882 predicates,
1883 } => {
1884 register_predicate_dependencies(dependents, &name, &predicates);
1885 let node = CategoryNode {
1886 name: name.clone(),
1887 meta,
1888 children,
1889 predicates,
1890 };
1891 Ok((name, Node::Category(node)))
1892 }
1893 NodeDecl::SwissKnife(decl) => {
1894 let name = decl.name;
1895 let meta = decl.meta;
1896 let expr = decl.expr;
1897 let variables = decl.variables;
1898 let output = decl.output;
1899 let predicates = decl.predicates;
1900 let mut ast = parse_expression(&expr).map_err(|err| GenApiError::ExprParse {
1901 name: name.clone(),
1902 msg: err.to_string(),
1903 })?;
1904 substitute(&mut ast, &formula_bindings(&name, &decl.bindings)?);
1905 let mut used = HashSet::new();
1906 collect_identifiers(&ast, &mut used);
1907 for ident in &used {
1908 if !variables.iter().any(|(var, _)| var == ident) && !is_builtin_constant(ident) {
1911 return Err(GenApiError::UnknownVariable {
1912 name: name.clone(),
1913 var: ident.clone(),
1914 });
1915 }
1916 }
1917 for (_, provider) in &variables {
1918 dependents
1919 .entry(provider.clone())
1920 .or_default()
1921 .push(name.clone());
1922 }
1923 register_predicate_dependencies(dependents, &name, &predicates);
1924 let node = SkNode {
1925 name: name.clone(),
1926 meta,
1927 output,
1928 ast,
1929 vars: variables,
1930 predicates,
1931 cache: std::cell::RefCell::new(None),
1932 };
1933 Ok((name, Node::SwissKnife(node)))
1934 }
1935 NodeDecl::Converter(decl) => {
1936 let name = decl.name;
1937 let bindings = formula_bindings(&name, &decl.bindings)?;
1938 let mut ast_to =
1939 parse_expression(&decl.formula_to).map_err(|err| GenApiError::ExprParse {
1940 name: name.clone(),
1941 msg: format!("FormulaTo: {err}"),
1942 })?;
1943 substitute(&mut ast_to, &bindings);
1944 let mut ast_from =
1945 parse_expression(&decl.formula_from).map_err(|err| GenApiError::ExprParse {
1946 name: name.clone(),
1947 msg: format!("FormulaFrom: {err}"),
1948 })?;
1949 substitute(&mut ast_from, &bindings);
1950 for (_, provider) in &decl.variables_to {
1952 dependents
1953 .entry(provider.clone())
1954 .or_default()
1955 .push(name.clone());
1956 }
1957 for (_, provider) in &decl.variables_from {
1958 if !decl.variables_to.iter().any(|(_, p)| p == provider) {
1959 dependents
1960 .entry(provider.clone())
1961 .or_default()
1962 .push(name.clone());
1963 }
1964 }
1965 dependents
1967 .entry(decl.p_value.clone())
1968 .or_default()
1969 .push(name.clone());
1970 register_predicate_dependencies(dependents, &name, &decl.predicates);
1971 let node = ConverterNode {
1972 name: name.clone(),
1973 meta: decl.meta,
1974 p_value: decl.p_value,
1975 ast_to,
1976 ast_from,
1977 vars_to: decl.variables_to,
1978 vars_from: decl.variables_from,
1979 unit: decl.unit,
1980 output: decl.output,
1981 predicates: decl.predicates,
1982 cache: std::cell::RefCell::new(None),
1983 };
1984 Ok((name, Node::Converter(node)))
1985 }
1986 NodeDecl::IntConverter(decl) => {
1987 let name = decl.name;
1988 let bindings = formula_bindings(&name, &decl.bindings)?;
1989 let mut ast_to =
1990 parse_expression(&decl.formula_to).map_err(|err| GenApiError::ExprParse {
1991 name: name.clone(),
1992 msg: format!("FormulaTo: {err}"),
1993 })?;
1994 substitute(&mut ast_to, &bindings);
1995 let mut ast_from =
1996 parse_expression(&decl.formula_from).map_err(|err| GenApiError::ExprParse {
1997 name: name.clone(),
1998 msg: format!("FormulaFrom: {err}"),
1999 })?;
2000 substitute(&mut ast_from, &bindings);
2001 for (_, provider) in &decl.variables_to {
2002 dependents
2003 .entry(provider.clone())
2004 .or_default()
2005 .push(name.clone());
2006 }
2007 for (_, provider) in &decl.variables_from {
2008 if !decl.variables_to.iter().any(|(_, p)| p == provider) {
2009 dependents
2010 .entry(provider.clone())
2011 .or_default()
2012 .push(name.clone());
2013 }
2014 }
2015 dependents
2016 .entry(decl.p_value.clone())
2017 .or_default()
2018 .push(name.clone());
2019 register_predicate_dependencies(dependents, &name, &decl.predicates);
2020 let node = IntConverterNode {
2021 name: name.clone(),
2022 meta: decl.meta,
2023 p_value: decl.p_value,
2024 ast_to,
2025 ast_from,
2026 vars_to: decl.variables_to,
2027 vars_from: decl.variables_from,
2028 unit: decl.unit,
2029 predicates: decl.predicates,
2030 cache: std::cell::RefCell::new(None),
2031 };
2032 Ok((name, Node::IntConverter(node)))
2033 }
2034 NodeDecl::String(decl) => {
2035 let name = decl.name;
2036 register_addressing_dependency(dependents, &name, &decl.addressing);
2037 register_predicate_dependencies(dependents, &name, &decl.predicates);
2038 let node = StringNode {
2039 name: name.clone(),
2040 meta: decl.meta,
2041 addressing: decl.addressing,
2042 access: decl.access,
2043 predicates: decl.predicates,
2044 cache: std::cell::RefCell::new(None),
2045 };
2046 Ok((name, Node::String(node)))
2047 }
2048 NodeDecl::Register(decl) => {
2049 let name = decl.name;
2050 register_addressing_dependency(dependents, &name, &decl.addressing);
2051 register_predicate_dependencies(dependents, &name, &decl.predicates);
2052 let node = RegisterNode {
2053 name: name.clone(),
2054 meta: decl.meta,
2055 addressing: decl.addressing,
2056 access: decl.access,
2057 port: decl.port,
2058 predicates: decl.predicates,
2059 cache: std::cell::RefCell::new(None),
2060 };
2061 Ok((name, Node::Register(node)))
2062 }
2063 other => Err(GenApiError::Unsupported(format!(
2069 "node '{}' has declaration kind '{}', which this nodemap cannot build; \
2070 viva-genapi-xml understands it but viva-genapi has no arm for it",
2071 other.name(),
2072 other.kind()
2073 ))),
2074 }
2075}
2076
2077fn integer_sign(node: &IntegerNode) -> Sign {
2091 node.sign
2092}
2093
2094fn formula_bindings(
2102 node: &str,
2103 declared: &FormulaBindings,
2104) -> Result<HashMap<String, SkAst>, GenApiError> {
2105 let mut bindings: HashMap<String, SkAst> = HashMap::new();
2106 for (name, literal) in &declared.constants {
2107 let value = parse_expression(literal).map_err(|err| GenApiError::ExprParse {
2108 name: node.to_string(),
2109 msg: format!("Constant {name}: {err}"),
2110 })?;
2111 bindings.insert(name.clone(), value);
2112 }
2113 for (name, formula) in &declared.expressions {
2114 let mut ast = parse_expression(formula).map_err(|err| GenApiError::ExprParse {
2115 name: node.to_string(),
2116 msg: format!("Expression {name}: {err}"),
2117 })?;
2118 substitute(&mut ast, &bindings);
2119 bindings.insert(name.clone(), ast);
2120 }
2121 Ok(bindings)
2122}
2123
2124fn sk_to_i64(name: &str, value: SkValue) -> Result<i64, GenApiError> {
2130 match value {
2131 SkValue::Int(value) => Ok(value),
2132 SkValue::Float(value) => round_to_i64(name, value),
2133 }
2134}
2135
2136fn eval_mode(output: SkOutput) -> EvalMode {
2138 match output {
2139 SkOutput::Integer => EvalMode::Integer,
2140 SkOutput::Float => EvalMode::Float,
2141 }
2142}
2143
2144fn expr_error(name: &str, err: SkEvalError) -> GenApiError {
2146 match err {
2147 SkEvalError::UnknownVariable(var) => GenApiError::UnknownVariable {
2148 name: name.to_string(),
2149 var,
2150 },
2151 SkEvalError::DivisionByZero => GenApiError::ExprEval {
2152 name: name.to_string(),
2153 msg: "division by zero".into(),
2154 },
2155 SkEvalError::UnknownFunction(func) => GenApiError::ExprEval {
2156 name: name.to_string(),
2157 msg: format!("unknown function: {func}"),
2158 },
2159 SkEvalError::ArityMismatch {
2160 name: func,
2161 expected,
2162 got,
2163 } => GenApiError::ExprEval {
2164 name: name.to_string(),
2165 msg: format!("function {func} expects {expected} args, got {got}"),
2166 },
2167 }
2168}
2169
2170impl TryFrom<XmlModel> for NodeMap {
2171 type Error = GenApiError;
2172
2173 fn try_from(model: XmlModel) -> Result<Self, Self::Error> {
2174 NodeMap::try_from_xml(model)
2175 }
2176}