use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Conditions {
#[serde(rename = "condition", default)]
pub conditions: Vec<Condition>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Condition {
pub id: String,
pub description: Option<String>,
#[serde(rename = "accept", default)]
pub accept: Vec<Filter>,
#[serde(rename = "require", default)]
pub require: Vec<Filter>,
#[serde(rename = "deny", default)]
pub deny: Vec<Filter>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
#[allow(clippy::too_long_first_doc_paragraph)]
pub struct Filter {
#[serde(rename = "Dvendor")]
pub device_vendor: Option<String>,
#[serde(rename = "Dname")]
pub device_name: Option<String>,
#[serde(rename = "Pname")]
pub processor_name: Option<String>,
#[serde(rename = "Dcore")]
pub device_core: Option<String>,
#[serde(rename = "Dfpu")]
pub fpu: Option<String>,
#[serde(rename = "Dmpu")]
pub mpu: Option<String>,
#[serde(rename = "Dtz")]
pub trustzone: Option<String>,
#[serde(rename = "Dsecure")]
pub secure: Option<String>,
#[serde(rename = "Ddsp")]
pub dsp: Option<String>,
#[serde(rename = "Dmve")]
pub mve: Option<String>,
#[serde(rename = "Dpacbti")]
pub pacbti: Option<String>,
#[serde(rename = "Dendian")]
pub endian: Option<String>,
#[serde(rename = "Cvendor")]
pub component_vendor: Option<String>,
#[serde(rename = "Cbundle")]
pub bundle: Option<String>,
#[serde(rename = "Cclass")]
pub class: Option<String>,
#[serde(rename = "Cgroup")]
pub group: Option<String>,
#[serde(rename = "Csub")]
pub sub: Option<String>,
#[serde(rename = "Cvariant")]
pub variant: Option<String>,
#[serde(rename = "Cversion")]
pub version: Option<String>,
#[serde(rename = "Capiversion")]
pub api_version: Option<String>,
#[serde(rename = "Bvendor")]
pub board_vendor: Option<String>,
#[serde(rename = "Bname")]
pub board_name: Option<String>,
#[serde(rename = "Brevision")]
pub board_revision: Option<String>,
#[serde(rename = "Hvendor")]
pub part_vendor: Option<String>,
#[serde(rename = "Hname")]
pub part_name: Option<String>,
#[serde(rename = "Tcompiler")]
pub compiler: Option<String>,
#[serde(rename = "Toptions")]
pub compiler_options: Option<String>,
#[serde(rename = "Toutput")]
pub compiler_output: Option<String>,
pub condition: Option<String>,
#[serde(rename = "Dfamily")]
pub d_family: Option<String>,
#[serde(rename = "DsubFamily")]
pub d_sub_family: Option<String>,
#[serde(rename = "Dvariant")]
pub d_variant: Option<String>,
}
#[cfg(test)]
mod tests {
use crate::conditions::Conditions;
#[test]
fn parse_conditions() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<conditions>
<condition id="CM4">
<description>Requires ARM Cortex-M4 with FPU</description>
<accept Dcore="Cortex-M4" Dfpu="SP_FPU"/>
<accept Dcore="Cortex-M4" Dfpu="DP_FPU"/>
<require Tcompiler="GCC"/>
<deny Dcore="Cortex-M0"/>
</condition>
<condition id="GCC_Only">
<require Tcompiler="GCC"/>
</condition>
</conditions>"#;
let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
assert_eq!(conds.conditions.len(), 2);
let c0 = &conds.conditions[0];
assert_eq!(c0.id, "CM4");
assert_eq!(
c0.description,
Some("Requires ARM Cortex-M4 with FPU".to_string())
);
assert_eq!(c0.accept.len(), 2);
assert_eq!(c0.accept[0].device_core, Some("Cortex-M4".to_string()));
assert_eq!(c0.accept[0].fpu, Some("SP_FPU".to_string()));
assert_eq!(c0.accept[1].device_core, Some("Cortex-M4".to_string()));
assert_eq!(c0.accept[1].fpu, Some("DP_FPU".to_string()));
assert_eq!(c0.require.len(), 1);
assert_eq!(c0.require[0].compiler, Some("GCC".to_string()));
assert_eq!(c0.deny.len(), 1);
assert_eq!(c0.deny[0].device_core, Some("Cortex-M0".to_string()));
let c1 = &conds.conditions[1];
assert_eq!(c1.id, "GCC_Only");
assert_eq!(c1.description, None);
assert_eq!(c1.accept.len(), 0);
assert_eq!(c1.require.len(), 1);
assert_eq!(c1.deny.len(), 0);
}
#[test]
fn parse_condition_minimal() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<conditions>
<condition id="Empty"/>
</conditions>"#;
let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
assert_eq!(conds.conditions.len(), 1);
let c = &conds.conditions[0];
assert_eq!(c.id, "Empty");
assert_eq!(c.description, None);
assert_eq!(c.accept, vec![]);
assert_eq!(c.require, vec![]);
assert_eq!(c.deny, vec![]);
}
#[test]
fn parse_condition_filters() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<conditions>
<condition id="Complex">
<accept Dvendor="ARM:82" Dname="ARMCM4*" Dcore="Cortex-M4"
Dfpu="SP_FPU" Dmpu="MPU" Dtz="TZ" Dsecure="Secure"
Ddsp="DSP" Dmve="MVE" Dpacbti="PACBTI"
Dendian="Little-endian" Pname="Core0"/>
<require Cclass="CMSIS" Cgroup="RTOS2" Capiversion="2.0.0"
Cvendor="ARM" Cbundle="CMSIS" Csub="Core"
Cvariant="Release" Cversion="5.0.0"/>
<require Bvendor="ARM" Bname="V2M-MPS2" Brevision="Rev.C"
Hvendor="NXP" Hname="LPC1768"
Tcompiler="GCC" Toptions="AC6" Toutput="exe"/>
<deny condition="NoARM"/>
</condition>
</conditions>"#;
let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
let c = &conds.conditions[0];
assert_eq!(c.id, "Complex");
let a = &c.accept[0];
assert_eq!(a.device_vendor, Some("ARM:82".to_string()));
assert_eq!(a.device_name, Some("ARMCM4*".to_string()));
assert_eq!(a.device_core, Some("Cortex-M4".to_string()));
assert_eq!(a.fpu, Some("SP_FPU".to_string()));
assert_eq!(a.mpu, Some("MPU".to_string()));
assert_eq!(a.trustzone, Some("TZ".to_string()));
assert_eq!(a.secure, Some("Secure".to_string()));
assert_eq!(a.dsp, Some("DSP".to_string()));
assert_eq!(a.mve, Some("MVE".to_string()));
assert_eq!(a.pacbti, Some("PACBTI".to_string()));
assert_eq!(a.endian, Some("Little-endian".to_string()));
assert_eq!(a.processor_name, Some("Core0".to_string()));
assert_eq!(a.condition, None);
let r0 = &c.require[0];
assert_eq!(r0.class, Some("CMSIS".to_string()));
assert_eq!(r0.group, Some("RTOS2".to_string()));
assert_eq!(r0.api_version, Some("2.0.0".to_string()));
assert_eq!(r0.component_vendor, Some("ARM".to_string()));
assert_eq!(r0.bundle, Some("CMSIS".to_string()));
assert_eq!(r0.sub, Some("Core".to_string()));
assert_eq!(r0.variant, Some("Release".to_string()));
assert_eq!(r0.version, Some("5.0.0".to_string()));
assert_eq!(r0.device_vendor, None);
let r1 = &c.require[1];
assert_eq!(r1.board_vendor, Some("ARM".to_string()));
assert_eq!(r1.board_name, Some("V2M-MPS2".to_string()));
assert_eq!(r1.board_revision, Some("Rev.C".to_string()));
assert_eq!(r1.part_vendor, Some("NXP".to_string()));
assert_eq!(r1.part_name, Some("LPC1768".to_string()));
assert_eq!(r1.compiler, Some("GCC".to_string()));
assert_eq!(r1.compiler_options, Some("AC6".to_string()));
assert_eq!(r1.compiler_output, Some("exe".to_string()));
assert_eq!(r1.class, None);
let d = &c.deny[0];
assert_eq!(d.condition, Some("NoARM".to_string()));
assert_eq!(d.device_vendor, None);
}
#[test]
fn parse_deprecated_filter_attrs() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<conditions>
<condition id="LegacyDeviceFilter">
<require Dfamily="STM32F4" DsubFamily="STM32F405" Dvariant="STM32F405RGTx"/>
<accept Dfamily="NXP_LPC" DsubFamily="LPC176x" Dvariant="LPC1769"/>
</condition>
</conditions>"#;
let conds: Conditions = serde_roxmltree::from_str(xml_str).unwrap();
assert_eq!(conds.conditions.len(), 1);
let c = &conds.conditions[0];
assert_eq!(c.id, "LegacyDeviceFilter");
let r = &c.require[0];
assert_eq!(r.d_family, Some("STM32F4".to_string()));
assert_eq!(r.d_sub_family, Some("STM32F405".to_string()));
assert_eq!(r.d_variant, Some("STM32F405RGTx".to_string()));
assert_eq!(r.device_vendor, None);
assert_eq!(r.device_name, None);
let a = &c.accept[0];
assert_eq!(a.d_family, Some("NXP_LPC".to_string()));
assert_eq!(a.d_sub_family, Some("LPC176x".to_string()));
assert_eq!(a.d_variant, Some("LPC1769".to_string()));
}
}