use std::cell::RefCell;
use std::collections::HashMap;
use viva_genapi_xml::{AccessMode, Addressing, BitField, EnumEntryDecl};
pub use viva_genapi_xml::{NodeMeta, Representation, SkOutput, Visibility};
use crate::swissknife::AstNode;
#[derive(Debug)]
pub enum Node {
Integer(IntegerNode),
Float(FloatNode),
Enum(EnumNode),
Boolean(BooleanNode),
Command(CommandNode),
Category(CategoryNode),
SwissKnife(SkNode),
Converter(ConverterNode),
IntConverter(IntConverterNode),
String(StringNode),
}
impl Node {
pub fn kind_name(&self) -> &'static str {
match self {
Node::Integer(_) => "Integer",
Node::Float(_) => "Float",
Node::Enum(_) => "Enumeration",
Node::Boolean(_) => "Boolean",
Node::Command(_) => "Command",
Node::Category(_) => "Category",
Node::SwissKnife(_) => "SwissKnife",
Node::Converter(_) => "Converter",
Node::IntConverter(_) => "IntConverter",
Node::String(_) => "StringReg",
}
}
pub fn access_mode(&self) -> Option<viva_genapi_xml::AccessMode> {
match self {
Node::Integer(n) => Some(n.access),
Node::Float(n) => Some(n.access),
Node::Enum(n) => Some(n.access),
Node::Boolean(n) => Some(n.access),
Node::Command(_) => Some(viva_genapi_xml::AccessMode::WO),
Node::Category(_) => None,
Node::SwissKnife(_) => Some(viva_genapi_xml::AccessMode::RO),
Node::Converter(_) => Some(viva_genapi_xml::AccessMode::RO),
Node::IntConverter(_) => Some(viva_genapi_xml::AccessMode::RO),
Node::String(n) => Some(n.access),
}
}
pub fn name(&self) -> &str {
match self {
Node::Integer(n) => &n.name,
Node::Float(n) => &n.name,
Node::Enum(n) => &n.name,
Node::Boolean(n) => &n.name,
Node::Command(n) => &n.name,
Node::Category(n) => &n.name,
Node::SwissKnife(n) => &n.name,
Node::Converter(n) => &n.name,
Node::IntConverter(n) => &n.name,
Node::String(n) => &n.name,
}
}
pub fn meta(&self) -> &NodeMeta {
match self {
Node::Integer(n) => &n.meta,
Node::Float(n) => &n.meta,
Node::Enum(n) => &n.meta,
Node::Boolean(n) => &n.meta,
Node::Command(n) => &n.meta,
Node::Category(n) => &n.meta,
Node::SwissKnife(n) => &n.meta,
Node::Converter(n) => &n.meta,
Node::IntConverter(n) => &n.meta,
Node::String(n) => &n.meta,
}
}
pub fn visibility(&self) -> Visibility {
self.meta().visibility
}
pub fn description(&self) -> Option<&str> {
self.meta().description.as_deref()
}
pub fn tooltip(&self) -> Option<&str> {
self.meta().tooltip.as_deref()
}
pub fn display_name(&self) -> Option<&str> {
self.meta().display_name.as_deref()
}
pub fn representation(&self) -> Option<Representation> {
self.meta().representation
}
pub(crate) fn invalidate_cache(&self) {
match self {
Node::Integer(node) => {
node.cache.replace(None);
node.raw_cache.replace(None);
}
Node::Float(node) => {
node.cache.replace(None);
}
Node::Enum(node) => node.invalidate(),
Node::Boolean(node) => {
node.cache.replace(None);
node.raw_cache.replace(None);
}
Node::SwissKnife(node) => {
node.cache.replace(None);
}
Node::Converter(node) => {
node.cache.replace(None);
}
Node::IntConverter(node) => {
node.cache.replace(None);
}
Node::String(node) => {
node.cache.replace(None);
}
Node::Command(_) | Node::Category(_) => {}
}
}
}
#[derive(Debug)]
pub struct IntegerNode {
pub name: String,
pub meta: NodeMeta,
pub addressing: Option<Addressing>,
pub len: u32,
pub access: AccessMode,
pub min: i64,
pub max: i64,
pub inc: Option<i64>,
pub unit: Option<String>,
pub bitfield: Option<BitField>,
pub selectors: Vec<String>,
pub selected_if: Vec<(String, Vec<String>)>,
pub pvalue: Option<String>,
pub p_max: Option<String>,
pub p_min: Option<String>,
pub value: Option<i64>,
pub(crate) cache: RefCell<Option<i64>>,
pub(crate) raw_cache: RefCell<Option<Vec<u8>>>,
}
#[derive(Debug)]
pub struct FloatNode {
pub name: String,
pub meta: NodeMeta,
pub addressing: Option<Addressing>,
pub access: AccessMode,
pub min: f64,
pub max: f64,
pub unit: Option<String>,
pub scale: Option<(i64, i64)>,
pub offset: Option<f64>,
pub selectors: Vec<String>,
pub selected_if: Vec<(String, Vec<String>)>,
pub pvalue: Option<String>,
pub(crate) cache: RefCell<Option<f64>>,
}
#[derive(Debug)]
pub struct EnumNode {
pub name: String,
pub meta: NodeMeta,
pub addressing: Option<Addressing>,
pub access: AccessMode,
pub pvalue: Option<String>,
pub entries: Vec<EnumEntryDecl>,
pub default: Option<String>,
pub selectors: Vec<String>,
pub selected_if: Vec<(String, Vec<String>)>,
pub providers: Vec<String>,
pub(crate) value_cache: RefCell<Option<String>>,
pub(crate) mapping_cache: RefCell<Option<EnumMapping>>,
}
#[derive(Debug, Clone)]
pub(crate) struct EnumMapping {
pub by_value: HashMap<i64, String>,
pub by_name: HashMap<String, i64>,
}
impl EnumNode {
pub(crate) fn invalidate(&self) {
self.value_cache.replace(None);
self.mapping_cache.replace(None);
}
}
#[derive(Debug)]
pub struct BooleanNode {
pub name: String,
pub meta: NodeMeta,
pub addressing: Option<Addressing>,
pub len: u32,
pub access: AccessMode,
pub bitfield: Option<BitField>,
pub selectors: Vec<String>,
pub selected_if: Vec<(String, Vec<String>)>,
pub pvalue: Option<String>,
pub on_value: Option<i64>,
pub off_value: Option<i64>,
pub(crate) cache: RefCell<Option<bool>>,
pub(crate) raw_cache: RefCell<Option<Vec<u8>>>,
}
#[derive(Debug)]
pub struct SkNode {
pub name: String,
pub meta: NodeMeta,
pub output: SkOutput,
pub ast: AstNode,
pub vars: Vec<(String, String)>,
pub cache: RefCell<Option<(f64, u64)>>,
}
#[derive(Debug)]
pub struct CommandNode {
pub name: String,
pub meta: NodeMeta,
pub address: Option<u64>,
pub len: u32,
pub pvalue: Option<String>,
pub command_value: Option<i64>,
}
#[derive(Debug)]
pub struct CategoryNode {
pub name: String,
pub meta: NodeMeta,
pub children: Vec<String>,
}
#[derive(Debug)]
pub struct ConverterNode {
pub name: String,
pub meta: NodeMeta,
pub p_value: String,
pub ast_to: AstNode,
pub ast_from: AstNode,
pub vars_to: Vec<(String, String)>,
pub vars_from: Vec<(String, String)>,
pub unit: Option<String>,
pub output: SkOutput,
pub cache: RefCell<Option<(f64, u64)>>,
}
#[derive(Debug)]
pub struct IntConverterNode {
pub name: String,
pub meta: NodeMeta,
pub p_value: String,
pub ast_to: AstNode,
pub ast_from: AstNode,
pub vars_to: Vec<(String, String)>,
pub vars_from: Vec<(String, String)>,
pub unit: Option<String>,
pub cache: RefCell<Option<(i64, u64)>>,
}
#[derive(Debug)]
pub struct StringNode {
pub name: String,
pub meta: NodeMeta,
pub addressing: Addressing,
pub access: AccessMode,
pub cache: RefCell<Option<(String, u64)>>,
}