1use serde::{Deserialize, Serialize};
4
5use crate::family::Family;
6
7#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
8pub struct Description {
11 pub overview: Option<String>,
13
14 #[serde(rename = "#content")]
16 pub content: Option<String>,
17}
18
19#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
20pub struct Eccn {
22 #[serde(rename = "ECCN-EU")]
23 pub eu: String,
24 #[serde(rename = "ECCN-US")]
25 pub us: String,
26}
27
28#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
29pub struct LicenseSets {
32 #[serde(rename = "licenseSet")]
33 pub license_set: Vec<LicenseSet>,
34}
35
36#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
37pub struct LicenseSet {
39 pub id: String,
41 pub default: Option<bool>,
43 pub gating: Option<bool>,
45 pub license: Vec<License>,
47}
48
49#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
50pub struct License {
55 pub name: String,
57
58 pub title: String,
60
61 pub spdx: Option<String>,
63
64 pub url: Option<String>,
66}
67
68#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
69pub struct Dominate {
71 pub info: String,
73}
74
75#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
76pub struct Repository {
78 #[serde(rename = "type")]
79 pub repository_type: Option<String>,
80
81 #[serde(rename = "#content")]
82 pub url: String,
83}
84
85#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
86pub struct Releases {
88 pub release: Vec<Release>,
89}
90
91#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
92pub struct Release {
94 pub version: String,
96 pub date: Option<String>,
98 pub tag: Option<String>,
100 pub url: Option<String>,
102 pub deprecated: Option<String>,
104 pub replacement: Option<String>,
106 #[serde(rename = "#content")]
107 pub content: String,
108}
109
110#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
111pub struct Changelogs {
113 pub changelog: Vec<Changelog>,
114}
115
116#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
117pub struct Changelog {
119 pub id: String,
121
122 pub name: String,
124
125 pub default: Option<bool>,
127
128 #[serde(rename = "type")]
130 pub changelog_type: Option<String>,
131}
132
133#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
134pub struct Keywords {
136 #[serde(rename = "keyword")]
138 pub keywords: Vec<String>,
139}
140
141#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
142pub struct Environments {
144 #[serde(rename = "environment")]
146 pub environments: Vec<Environment>,
147}
148
149#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
150pub struct Environment {
152 pub name: String,
153 #[serde(rename = "Pname")]
154 pub processor_name: Option<String>,
155 }
157
158#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
160pub struct Devices<'a> {
161 #[serde(rename = "family", default)]
163 #[serde(borrow)]
164 pub families: Vec<Family<'a>>,
165}
166
167#[cfg(test)]
168mod tests {
169 use std::default;
170
171 use crate::pdsc::{
172 Changelogs, Devices, Eccn, License, LicenseSet, Release, Releases, Repository,
173 };
174 #[test]
175 fn parse_eccn() {
176 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
177<ECCN>
178 <ECCN-EU>NEC</ECCN-EU>
179 <ECCN-US>5D992.c</ECCN-US>
180</ECCN>"#;
181
182 let eccn: Eccn = serde_roxmltree::from_str(xml_str).unwrap();
183
184 assert_eq!(eccn.eu, "NEC".to_string());
185 assert_eq!(eccn.us, "5D992.c".to_string());
186 }
187
188 #[test]
189 fn parse_eccn_missing_field() {
194 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
195<ECCN>
196 <ECCN-US>5D992.c</ECCN-US>
197</ECCN>"#;
198
199 let eccn: Result<Eccn, _> = serde_roxmltree::from_str(xml_str);
200
201 assert!(eccn.is_err());
202
203 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
204<ECCN>
205 <ECCN-EU>NEC</ECCN-EU>
206</ECCN>"#;
207
208 let eccn: Result<Eccn, _> = serde_roxmltree::from_str(xml_str);
209
210 assert!(eccn.is_err());
211 }
212
213 #[test]
214 fn parse_license_set() {
215 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
216<licenseSet id="all" default="true" gating="false">
217 <license name="LICENSE.txt"
218 title="Apache License, Version 2.0"
219 spdx="Apache-2.0"
220 url="https://www.apache.org/licenses/LICENSE-2.0"/>
221</licenseSet>"#;
222
223 let license_set: LicenseSet = serde_roxmltree::from_str(xml_str).unwrap();
224
225 assert_eq!(
226 license_set,
227 LicenseSet {
228 id: "all".to_string(),
229 default: Some(true),
230 gating: Some(false),
231 license: vec![License {
232 name: "LICENSE.txt".to_string(),
233 title: "Apache License, Version 2.0".to_string(),
234 spdx: Some("Apache-2.0".to_string()),
235 url: Some("https://www.apache.org/licenses/LICENSE-2.0".to_string())
236 }]
237 }
238 );
239 }
240
241 #[test]
242 fn parse_repository() {
243 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
244<repository type="git">https://github.com/ARM-software/CMSIS-Driver.git</repository>"#;
245
246 let repo: Repository = serde_roxmltree::from_str(xml_str).unwrap();
247
248 assert_eq!(repo.repository_type, Some("git".to_string()));
249 assert_eq!(
250 repo.url,
251 "https://github.com/ARM-software/CMSIS-Driver.git".to_string()
252 );
253 }
254
255 #[test]
256 fn parse_releases() {
257 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
258<releases>
259 <release version="1.1.1" date="2020-05-12">Fixed a problem with the feature xyz.</release>
260 <release version="1.1.0" date="2020-03-13">Introduces a new feature xyz.</release>
261 <release version="1.0.0" date="2020-02-23">First published version.</release>
262</releases>
263"#;
264
265 let releases: Releases = serde_roxmltree::from_str(xml_str).unwrap();
266
267 assert_eq!(
268 releases,
269 Releases {
270 release: vec![
271 Release {
272 version: "1.1.1".to_string(),
273 date: Some("2020-05-12".to_string()),
274 content: "Fixed a problem with the feature xyz.".to_string(),
275 ..default::Default::default()
276 },
277 Release {
278 version: "1.1.0".to_string(),
279 date: Some("2020-03-13".to_string()),
280 content: "Introduces a new feature xyz.".to_string(),
281 ..default::Default::default()
282 },
283 Release {
284 version: "1.0.0".to_string(),
285 date: Some("2020-02-23".to_string()),
286 content: "First published version.".to_string(),
287 ..default::Default::default()
288 },
289 ]
290 }
291 );
292 }
293
294 #[test]
295 fn parse_releases_public_repo() {
296 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
297<releases>
298 <release version="2.1.0" tag="2.1.0" url="https://github.com/ARM-software/CMSIS-Driver/archive/2.1.0.zip">
299 Added LAN9220 Ethernet MAC+PHY driver.
300 </release>
301 <release version="2.0.0" tag="2.0.0" url="https://github.com/ARM-software/CMSIS-Driver/archive/2.0.0.zip">
302 First published version.
303 </release>
304</releases>"#;
305
306 let releases: Releases = serde_roxmltree::from_str(xml_str).unwrap();
307
308 assert_eq!(
309 releases,
310 Releases {
311 release: vec![
312 Release {
313 version: "2.1.0".to_string(),
314 tag: Some("2.1.0".to_string()),
315 url: Some(
316 "https://github.com/ARM-software/CMSIS-Driver/archive/2.1.0.zip"
317 .to_string()
318 ),
319 content: "\n Added LAN9220 Ethernet MAC+PHY driver.\n ".to_string(),
320 ..default::Default::default()
321 },
322 Release {
323 version: "2.0.0".to_string(),
324 tag: Some("2.0.0".to_string()),
325 url: Some(
326 "https://github.com/ARM-software/CMSIS-Driver/archive/2.0.0.zip"
327 .to_string()
328 ),
329 content: "\n First published version.\n ".to_string(),
330 ..default::Default::default()
331 },
332 ]
333 }
334 );
335 }
336
337 #[test]
338 fn parse_releases_deprecated() {
339 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
340<releases>
341 <release version="1.0.1" date="2020-04-18" deprecated="2020-04-18" replacement="Vendor.pack_name">
342 </release>
343 <release version="1.0.0" date="2020-03-24">Initial version.
344 </release>
345</releases>"#;
346
347 let releases: Releases = serde_roxmltree::from_str(xml_str).unwrap();
348
349 assert_eq!(
350 releases,
351 Releases {
352 release: vec![
353 Release {
354 version: "1.0.1".to_string(),
355 date: Some("2020-04-18".to_string()),
356 deprecated: Some("2020-04-18".to_string()),
357 replacement: Some("Vendor.pack_name".to_string()),
358 content: "\n ".to_string(),
359 ..default::Default::default()
360 },
361 Release {
362 version: "1.0.0".to_string(),
363 date: Some("2020-03-24".to_string()),
364 content: "Initial version.\n ".to_string(),
365 ..default::Default::default()
366 },
367 ]
368 }
369 );
370 }
371
372 #[test]
373 fn parse_devices_multiple_families() {
374 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
375<devices>
376 <family Dfamily="FamilyA" Dvendor="ARM:82">
377 <debugvars configfile="a.dbgconf" version="1.0.0"></debugvars>
378 <sequences/>
379 </family>
380 <family Dfamily="FamilyB" Dvendor="ARM:82">
381 <debugvars configfile="b.dbgconf" version="2.0.0"></debugvars>
382 <sequences/>
383 </family>
384</devices>"#;
385 let document = roxmltree::Document::parse(xml_str).unwrap();
387 let devices: Devices = serde_roxmltree::from_doc(&document).unwrap();
388 assert_eq!(devices.families.len(), 2);
389 assert_eq!(devices.families[0].device_family, "FamilyA");
390 assert_eq!(devices.families[1].device_family, "FamilyB");
391 }
392
393 #[test]
394 fn parse_changelog_default_bool() {
395 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
396<changelogs>
397 <changelog id="all" name="CHANGELOG.md" default="true"/>
398 <changelog id="other" name="OTHER.md"/>
399</changelogs>"#;
400
401 let changelogs: Changelogs = serde_roxmltree::from_str(xml_str).unwrap();
402 assert_eq!(changelogs.changelog.len(), 2);
403 assert_eq!(changelogs.changelog[0].id, "all");
404 assert_eq!(changelogs.changelog[0].name, "CHANGELOG.md");
405 assert_eq!(changelogs.changelog[0].default, Some(true));
406 assert_eq!(changelogs.changelog[1].id, "other");
407 assert_eq!(changelogs.changelog[1].default, None);
408 }
409}