Skip to main content

cmsis_pdsc_parser/
requirements.rs

1//! Contains the types required for the [PDSC Requirements](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/element_requirements_pg.html) element
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
6/// Represents the [PDSC Requirements](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/element_requirements_pg.html#element_requirements)
7/// element
8pub struct Requirements {
9    /// List of software packs required for the project to build
10    pub packages: Option<PackagesList>,
11
12    /// List of compilers required for the project to build
13    pub compilers: Option<CompilersList>,
14
15    /// List of language standards required for the project to build.
16    pub languages: Option<LanguagesList>,
17
18    /// Restrict a software pack to a list of devices, boards, or processor cores.
19    pub targets: Option<TargetsList>,
20}
21
22#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
23/// Wrapper type for the `packages` xml element
24pub struct PackagesList {
25    #[serde(rename = "package")]
26    pub packages: Vec<Package>,
27}
28
29#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
30/// Wrapper type for the `compilers` xml element
31pub struct CompilersList {
32    #[serde(rename = "compiler")]
33    pub compilers: Vec<Compiler>,
34}
35
36#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
37/// Wrapper type for the `languages` xml element
38pub struct LanguagesList {
39    #[serde(rename = "language")]
40    pub languages: Vec<Language>,
41}
42
43#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
44/// Wrapper type for the `targets` xml element
45pub struct TargetsList {
46    #[serde(rename = "target")]
47    pub targets: Vec<Target>,
48}
49
50#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
51/// Represents the [PDSC PackagesType](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/element_requirements_pg.html#element_packages) element
52pub struct Package {
53    /// The package vendor; pattern: `RestrictedString` = `[A-Za-z0-9_\-]+`
54    pub vendor: String,
55
56    /// Name of the pack
57    pub name: String,
58
59    /// Version of the required pack; pattern: `VersionType` (e.g. `1.2.3` or `>=1.0.0`)
60    pub version: Option<String>,
61}
62
63#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
64/// Represents the [PDSC CompilersType](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/element_requirements_pg.html#element_compilers) element
65pub struct Compiler {
66    /// Name of the required compiler
67    pub name: String,
68
69    /// Version of the required compiler
70    pub version: String,
71}
72
73#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
74/// Represents the [PDSC Languages](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/element_requirements_pg.html#element_languages) element
75pub struct Language {
76    /// Name of the porgramming language, i.e. "C", "C++", "Rust"
77    pub name: String,
78
79    /// Version of the language standard
80    pub version: String,
81}
82
83#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
84/// Represents the [PDSC Targets](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/element_requirements_pg.html#element_targets) element
85pub struct Target {
86    #[serde(rename = "Dvendor")]
87    /// The silicon vendor of the device
88    pub device_vendor: Option<String>,
89
90    #[serde(rename = "Dname")]
91    /// The name of the device (wildcards possible)
92    pub device_name: Option<String>,
93
94    #[serde(rename = "Dcore")]
95    /// The name of the processor core
96    pub device_core: Option<String>,
97
98    #[serde(rename = "Bvendor")]
99    /// The name of the board vendor
100    pub board_vendor: Option<String>,
101
102    #[serde(rename = "Bname")]
103    /// The name of the board
104    pub board_name: Option<String>,
105
106    #[serde(rename = "Brevision")]
107    /// Specifies the board revision
108    pub board_revision: Option<String>,
109
110    /// Optional descriptive text content of the `target` element; empty string if absent
111    #[serde(rename = "#content")]
112    pub content: String,
113}
114
115#[cfg(test)]
116mod tests {
117    use crate::requirements::{
118        Compiler, CompilersList, Language, LanguagesList, Package, PackagesList, Requirements,
119        Target, TargetsList,
120    };
121
122    #[test]
123    fn isolate_fields() {
124        let xml_packages = r#"<?xml version="1.0"?><requirements><packages><package name="A" vendor="B"/></packages></requirements>"#;
125        let xml_compilers = r#"<?xml version="1.0"?><requirements><compilers><compiler name="ARMCC" version="5.0"/></compilers></requirements>"#;
126        let xml_languages = r#"<?xml version="1.0"?><requirements><languages><language name="C" version="99"/></languages></requirements>"#;
127        let xml_targets = r#"<?xml version="1.0"?><requirements><targets><target Dvendor="X:1" Dname="Y"/></targets></requirements>"#;
128
129        let r: Result<Requirements, _> = serde_roxmltree::from_str(xml_packages);
130        println!("packages: {:?}", r.err());
131        let r: Result<Requirements, _> = serde_roxmltree::from_str(xml_compilers);
132        println!("compilers: {:?}", r.err());
133        let r: Result<Requirements, _> = serde_roxmltree::from_str(xml_languages);
134        println!("languages: {:?}", r.err());
135        let r: Result<Requirements, _> = serde_roxmltree::from_str(xml_targets);
136        println!("targets: {:?}", r.err());
137    }
138
139    #[test]
140    /// Test that all requiremets fields parse correctly
141    fn parse_requirements() {
142        let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
143<requirements>
144    <packages>
145        <package name="STM32F4xx_DFP" vendor="Keil" version="2.8.0:2.8.0"/>
146    </packages>
147    <compilers>
148        <compiler name="ARMCC" version="5.0.0:6.0.0-0"/>
149    </compilers>
150    <languages>
151        <language name="C" version="99"/>
152    </languages>
153    <targets>
154        <target Dvendor="STMicroelectronics:13" Dname="STM32H7*"/>    <!-- supports STM32H7 device series -->
155        <target Dvendor="STMicroelectronics:13" Dname="STM32U585"/>   <!-- and supports STM32U585 device -->
156    </targets>
157</requirements>"#;
158
159        let requirements: Requirements = serde_roxmltree::from_str(xml_str).unwrap();
160
161        assert_eq!(
162            requirements.packages,
163            Some(PackagesList {
164                packages: vec![Package {
165                    name: "STM32F4xx_DFP".to_string(),
166                    vendor: "Keil".to_string(),
167                    version: Some("2.8.0:2.8.0".to_string())
168                }]
169            })
170        );
171        assert_eq!(
172            requirements.compilers,
173            Some(CompilersList {
174                compilers: vec![Compiler {
175                    name: "ARMCC".to_string(),
176                    version: "5.0.0:6.0.0-0".to_string()
177                }]
178            })
179        );
180        assert_eq!(
181            requirements.languages,
182            Some(LanguagesList {
183                languages: vec![Language {
184                    name: "C".to_string(),
185                    version: "99".to_string()
186                }]
187            })
188        );
189        assert_eq!(
190            requirements.targets,
191            Some(TargetsList {
192                targets: vec![
193                    Target {
194                        device_vendor: Some("STMicroelectronics:13".to_string()),
195                        device_name: Some("STM32H7*".to_string()),
196                        device_core: None,
197                        board_name: None,
198                        board_revision: None,
199                        board_vendor: None,
200                        content: String::new()
201                    },
202                    Target {
203                        device_vendor: Some("STMicroelectronics:13".to_string()),
204                        device_name: Some("STM32U585".to_string()),
205                        device_core: None,
206                        board_name: None,
207                        board_revision: None,
208                        board_vendor: None,
209                        content: String::new()
210                    }
211                ]
212            })
213        );
214    }
215}