1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
6pub struct Conditions {
10 #[serde(rename = "condition", default)]
12 pub conditions: Vec<Condition>,
13}
14
15#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
16pub struct Condition {
20 pub id: String,
22
23 pub description: Option<String>,
25
26 #[serde(rename = "accept", default)]
28 pub accept: Vec<Filter>,
29
30 #[serde(rename = "require", default)]
32 pub require: Vec<Filter>,
33
34 #[serde(rename = "deny", default)]
36 pub deny: Vec<Filter>,
37}
38
39#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
40#[allow(clippy::too_long_first_doc_paragraph)]
41pub struct Filter {
48 #[serde(rename = "Dvendor")]
50 pub device_vendor: Option<String>,
51
52 #[serde(rename = "Dname")]
54 pub device_name: Option<String>,
55
56 #[serde(rename = "Pname")]
58 pub processor_name: Option<String>,
59
60 #[serde(rename = "Dcore")]
62 pub device_core: Option<String>,
63
64 #[serde(rename = "Dfpu")]
66 pub fpu: Option<String>,
67
68 #[serde(rename = "Dmpu")]
70 pub mpu: Option<String>,
71
72 #[serde(rename = "Dtz")]
74 pub trustzone: Option<String>,
75
76 #[serde(rename = "Dsecure")]
78 pub secure: Option<String>,
79
80 #[serde(rename = "Ddsp")]
82 pub dsp: Option<String>,
83
84 #[serde(rename = "Dmve")]
86 pub mve: Option<String>,
87
88 #[serde(rename = "Dpacbti")]
90 pub pacbti: Option<String>,
91
92 #[serde(rename = "Dendian")]
94 pub endian: Option<String>,
95
96 #[serde(rename = "Cvendor")]
98 pub component_vendor: Option<String>,
99
100 #[serde(rename = "Cbundle")]
102 pub bundle: Option<String>,
103
104 #[serde(rename = "Cclass")]
106 pub class: Option<String>,
107
108 #[serde(rename = "Cgroup")]
110 pub group: Option<String>,
111
112 #[serde(rename = "Csub")]
114 pub sub: Option<String>,
115
116 #[serde(rename = "Cvariant")]
118 pub variant: Option<String>,
119
120 #[serde(rename = "Cversion")]
122 pub version: Option<String>,
123
124 #[serde(rename = "Capiversion")]
126 pub api_version: Option<String>,
127
128 #[serde(rename = "Bvendor")]
130 pub board_vendor: Option<String>,
131
132 #[serde(rename = "Bname")]
134 pub board_name: Option<String>,
135
136 #[serde(rename = "Brevision")]
138 pub board_revision: Option<String>,
139
140 #[serde(rename = "Hvendor")]
142 pub part_vendor: Option<String>,
143
144 #[serde(rename = "Hname")]
146 pub part_name: Option<String>,
147
148 #[serde(rename = "Tcompiler")]
150 pub compiler: Option<String>,
151
152 #[serde(rename = "Toptions")]
154 pub compiler_options: Option<String>,
155
156 #[serde(rename = "Toutput")]
158 pub compiler_output: Option<String>,
159
160 pub condition: Option<String>,
162
163 #[serde(rename = "Dfamily")]
165 pub d_family: Option<String>,
166
167 #[serde(rename = "DsubFamily")]
169 pub d_sub_family: Option<String>,
170
171 #[serde(rename = "Dvariant")]
173 pub d_variant: Option<String>,
174}
175
176#[cfg(test)]
177mod tests {
178 use crate::conditions::Conditions;
179
180 #[test]
181 fn parse_conditions() {
182 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
183<conditions>
184 <condition id="CM4">
185 <description>Requires ARM Cortex-M4 with FPU</description>
186 <accept Dcore="Cortex-M4" Dfpu="SP_FPU"/>
187 <accept Dcore="Cortex-M4" Dfpu="DP_FPU"/>
188 <require Tcompiler="GCC"/>
189 <deny Dcore="Cortex-M0"/>
190 </condition>
191 <condition id="GCC_Only">
192 <require Tcompiler="GCC"/>
193 </condition>
194</conditions>"#;
195
196 let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
197 assert_eq!(conds.conditions.len(), 2);
198
199 let c0 = &conds.conditions[0];
200 assert_eq!(c0.id, "CM4");
201 assert_eq!(
202 c0.description,
203 Some("Requires ARM Cortex-M4 with FPU".to_string())
204 );
205 assert_eq!(c0.accept.len(), 2);
206 assert_eq!(c0.accept[0].device_core, Some("Cortex-M4".to_string()));
207 assert_eq!(c0.accept[0].fpu, Some("SP_FPU".to_string()));
208 assert_eq!(c0.accept[1].device_core, Some("Cortex-M4".to_string()));
209 assert_eq!(c0.accept[1].fpu, Some("DP_FPU".to_string()));
210 assert_eq!(c0.require.len(), 1);
211 assert_eq!(c0.require[0].compiler, Some("GCC".to_string()));
212 assert_eq!(c0.deny.len(), 1);
213 assert_eq!(c0.deny[0].device_core, Some("Cortex-M0".to_string()));
214
215 let c1 = &conds.conditions[1];
216 assert_eq!(c1.id, "GCC_Only");
217 assert_eq!(c1.description, None);
218 assert_eq!(c1.accept.len(), 0);
219 assert_eq!(c1.require.len(), 1);
220 assert_eq!(c1.deny.len(), 0);
221 }
222
223 #[test]
224 fn parse_condition_minimal() {
225 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
226<conditions>
227 <condition id="Empty"/>
228</conditions>"#;
229
230 let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
231 assert_eq!(conds.conditions.len(), 1);
232
233 let c = &conds.conditions[0];
234 assert_eq!(c.id, "Empty");
235 assert_eq!(c.description, None);
236 assert_eq!(c.accept, vec![]);
237 assert_eq!(c.require, vec![]);
238 assert_eq!(c.deny, vec![]);
239 }
240
241 #[test]
242 fn parse_condition_filters() {
243 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
244<conditions>
245 <condition id="Complex">
246 <accept Dvendor="ARM:82" Dname="ARMCM4*" Dcore="Cortex-M4"
247 Dfpu="SP_FPU" Dmpu="MPU" Dtz="TZ" Dsecure="Secure"
248 Ddsp="DSP" Dmve="MVE" Dpacbti="PACBTI"
249 Dendian="Little-endian" Pname="Core0"/>
250 <require Cclass="CMSIS" Cgroup="RTOS2" Capiversion="2.0.0"
251 Cvendor="ARM" Cbundle="CMSIS" Csub="Core"
252 Cvariant="Release" Cversion="5.0.0"/>
253 <require Bvendor="ARM" Bname="V2M-MPS2" Brevision="Rev.C"
254 Hvendor="NXP" Hname="LPC1768"
255 Tcompiler="GCC" Toptions="AC6" Toutput="exe"/>
256 <deny condition="NoARM"/>
257 </condition>
258</conditions>"#;
259
260 let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
261 let c = &conds.conditions[0];
262 assert_eq!(c.id, "Complex");
263
264 let a = &c.accept[0];
266 assert_eq!(a.device_vendor, Some("ARM:82".to_string()));
267 assert_eq!(a.device_name, Some("ARMCM4*".to_string()));
268 assert_eq!(a.device_core, Some("Cortex-M4".to_string()));
269 assert_eq!(a.fpu, Some("SP_FPU".to_string()));
270 assert_eq!(a.mpu, Some("MPU".to_string()));
271 assert_eq!(a.trustzone, Some("TZ".to_string()));
272 assert_eq!(a.secure, Some("Secure".to_string()));
273 assert_eq!(a.dsp, Some("DSP".to_string()));
274 assert_eq!(a.mve, Some("MVE".to_string()));
275 assert_eq!(a.pacbti, Some("PACBTI".to_string()));
276 assert_eq!(a.endian, Some("Little-endian".to_string()));
277 assert_eq!(a.processor_name, Some("Core0".to_string()));
278 assert_eq!(a.condition, None);
279
280 let r0 = &c.require[0];
282 assert_eq!(r0.class, Some("CMSIS".to_string()));
283 assert_eq!(r0.group, Some("RTOS2".to_string()));
284 assert_eq!(r0.api_version, Some("2.0.0".to_string()));
285 assert_eq!(r0.component_vendor, Some("ARM".to_string()));
286 assert_eq!(r0.bundle, Some("CMSIS".to_string()));
287 assert_eq!(r0.sub, Some("Core".to_string()));
288 assert_eq!(r0.variant, Some("Release".to_string()));
289 assert_eq!(r0.version, Some("5.0.0".to_string()));
290 assert_eq!(r0.device_vendor, None);
291
292 let r1 = &c.require[1];
294 assert_eq!(r1.board_vendor, Some("ARM".to_string()));
295 assert_eq!(r1.board_name, Some("V2M-MPS2".to_string()));
296 assert_eq!(r1.board_revision, Some("Rev.C".to_string()));
297 assert_eq!(r1.part_vendor, Some("NXP".to_string()));
298 assert_eq!(r1.part_name, Some("LPC1768".to_string()));
299 assert_eq!(r1.compiler, Some("GCC".to_string()));
300 assert_eq!(r1.compiler_options, Some("AC6".to_string()));
301 assert_eq!(r1.compiler_output, Some("exe".to_string()));
302 assert_eq!(r1.class, None);
303
304 let d = &c.deny[0];
306 assert_eq!(d.condition, Some("NoARM".to_string()));
307 assert_eq!(d.device_vendor, None);
308 }
309
310 #[test]
311 fn parse_deprecated_filter_attrs() {
312 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
315<conditions>
316 <condition id="LegacyDeviceFilter">
317 <require Dfamily="STM32F4" DsubFamily="STM32F405" Dvariant="STM32F405RGTx"/>
318 <accept Dfamily="NXP_LPC" DsubFamily="LPC176x" Dvariant="LPC1769"/>
319 </condition>
320</conditions>"#;
321
322 let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
323 assert_eq!(conds.conditions.len(), 1);
324
325 let c = &conds.conditions[0];
326 assert_eq!(c.id, "LegacyDeviceFilter");
327
328 let r = &c.require[0];
329 assert_eq!(r.d_family, Some("STM32F4".to_string()));
330 assert_eq!(r.d_sub_family, Some("STM32F405".to_string()));
331 assert_eq!(r.d_variant, Some("STM32F405RGTx".to_string()));
332 assert_eq!(r.device_vendor, None);
334 assert_eq!(r.device_name, None);
335
336 let a = &c.accept[0];
337 assert_eq!(a.d_family, Some("NXP_LPC".to_string()));
338 assert_eq!(a.d_sub_family, Some("LPC176x".to_string()));
339 assert_eq!(a.d_variant, Some("LPC1769".to_string()));
340 }
341}