1mod boolean;
6mod category;
7mod command;
8mod converter;
9mod elem_name;
10mod elem_type;
11mod enumeration;
12mod float;
13mod float_reg;
14mod formula;
15mod group;
16mod int_converter;
17mod int_reg;
18mod int_swiss_knife;
19mod integer;
20mod masked_int_reg;
21mod node;
22mod node_base;
23mod port;
24mod register;
25mod register_base;
26mod register_description;
27mod string;
28mod string_reg;
29mod struct_reg;
30mod swiss_knife;
31mod utils;
32mod xml;
33
34use group::GroupNode;
35use struct_reg::StructRegNode;
36use thiserror::Error;
37
38use crate::{
39 builder::{CacheStoreBuilder, NodeStoreBuilder, ValueStoreBuilder},
40 store::NodeData,
41 RegisterDescription,
42};
43
44use elem_name::{
45 ADV_FEATURE_LOCK, BOOLEAN, CATEGORY, COMMAND, CONF_ROM, CONVERTER, ENUMERATION, FLOAT,
46 FLOAT_REG, GROUP, INTEGER, INT_CONVERTER, INT_KEY, INT_REG, INT_SWISS_KNIFE, MASKED_INT_REG,
47 NODE, PORT, REGISTER, SMART_FEATURE, STRING, STRING_REG, STRUCT_REG, SWISS_KNIFE, TEXT_DESC,
48};
49
50#[derive(Debug, Error)]
51pub enum ParseError {
52 #[error("encodings must be UTF8: {0}")]
53 Utf8Error(#[from] std::str::Utf8Error),
54
55 #[error("invalid XML syntax: {0}")]
56 InvalidSyntax(#[from] roxmltree::Error),
57}
58
59pub type ParseResult<T> = std::result::Result<T, ParseError>;
60
61pub fn parse(
62 xml: &impl AsRef<str>,
63 node_builder: &mut impl NodeStoreBuilder,
64 value_builder: &mut impl ValueStoreBuilder,
65 cache_builder: &mut impl CacheStoreBuilder,
66) -> ParseResult<RegisterDescription> {
67 let document = xml::Document::from_str(xml.as_ref())?;
68 let mut node = document.root_node();
69 let reg_desc = node.parse(node_builder, value_builder, cache_builder);
70 while let Some(ref mut child) = node.next() {
71 let children: Vec<NodeData> = child.parse(node_builder, value_builder, cache_builder);
72 for child in children {
73 let id = child.node_base().id();
74 node_builder.store_node(id, child);
75 }
76 }
77
78 Ok(reg_desc)
79}
80
81trait Parse {
82 fn parse(
83 node: &mut xml::Node,
84 node_builder: &mut impl NodeStoreBuilder,
85 value_builder: &mut impl ValueStoreBuilder,
86 cache_builder: &mut impl CacheStoreBuilder,
87 ) -> Self;
88}
89
90impl Parse for Vec<NodeData> {
91 #[allow(clippy::too_many_lines)]
92 fn parse(
93 node: &mut xml::Node,
94 node_builder: &mut impl NodeStoreBuilder,
95 value_builder: &mut impl ValueStoreBuilder,
96 cache_builder: &mut impl CacheStoreBuilder,
97 ) -> Self {
98 match node.tag_name() {
99 NODE => vec![NodeData::Node(Box::new(node.parse(
100 node_builder,
101 value_builder,
102 cache_builder,
103 )))],
104 CATEGORY => vec![NodeData::Category(Box::new(node.parse(
105 node_builder,
106 value_builder,
107 cache_builder,
108 )))],
109 INTEGER => vec![NodeData::Integer(Box::new(node.parse(
110 node_builder,
111 value_builder,
112 cache_builder,
113 )))],
114 INT_REG => vec![NodeData::IntReg(Box::new(node.parse(
115 node_builder,
116 value_builder,
117 cache_builder,
118 )))],
119 MASKED_INT_REG => vec![NodeData::MaskedIntReg(Box::new(node.parse(
120 node_builder,
121 value_builder,
122 cache_builder,
123 )))],
124 BOOLEAN => vec![NodeData::Boolean(Box::new(node.parse(
125 node_builder,
126 value_builder,
127 cache_builder,
128 )))],
129 COMMAND => vec![NodeData::Command(Box::new(node.parse(
130 node_builder,
131 value_builder,
132 cache_builder,
133 )))],
134 ENUMERATION => vec![NodeData::Enumeration(Box::new(node.parse(
135 node_builder,
136 value_builder,
137 cache_builder,
138 )))],
139 FLOAT => vec![NodeData::Float(Box::new(node.parse(
140 node_builder,
141 value_builder,
142 cache_builder,
143 )))],
144 FLOAT_REG => vec![NodeData::FloatReg(Box::new(node.parse(
145 node_builder,
146 value_builder,
147 cache_builder,
148 )))],
149 STRING => vec![NodeData::String(Box::new(node.parse(
150 node_builder,
151 value_builder,
152 cache_builder,
153 )))],
154 STRING_REG => vec![NodeData::StringReg(Box::new(node.parse(
155 node_builder,
156 value_builder,
157 cache_builder,
158 )))],
159 REGISTER => vec![NodeData::Register(Box::new(node.parse(
160 node_builder,
161 value_builder,
162 cache_builder,
163 )))],
164 CONVERTER => vec![NodeData::Converter(Box::new(node.parse(
165 node_builder,
166 value_builder,
167 cache_builder,
168 )))],
169 INT_CONVERTER => vec![NodeData::IntConverter(Box::new(node.parse(
170 node_builder,
171 value_builder,
172 cache_builder,
173 )))],
174 SWISS_KNIFE => vec![NodeData::SwissKnife(Box::new(node.parse(
175 node_builder,
176 value_builder,
177 cache_builder,
178 )))],
179 INT_SWISS_KNIFE => vec![NodeData::IntSwissKnife(Box::new(node.parse(
180 node_builder,
181 value_builder,
182 cache_builder,
183 )))],
184 PORT => vec![NodeData::Port(Box::new(node.parse(
185 node_builder,
186 value_builder,
187 cache_builder,
188 )))],
189 STRUCT_REG => {
190 let node: StructRegNode = node.parse(node_builder, value_builder, cache_builder);
191 node.into_masked_int_regs(cache_builder)
192 .into_iter()
193 .map(|node| NodeData::MaskedIntReg(node.into()))
194 .collect()
195 }
196 GROUP => {
197 let node: GroupNode = node.parse(node_builder, value_builder, cache_builder);
198 node.nodes
199 }
200 CONF_ROM | TEXT_DESC | INT_KEY | ADV_FEATURE_LOCK | SMART_FEATURE => todo!(),
202 _ => unreachable!(),
203 }
204 }
205}