1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
6pub struct Apis {
10 #[serde(rename = "api", default)]
12 pub apis: Vec<Api>,
13}
14
15#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
16pub struct Api {
20 #[serde(rename = "Cclass")]
22 pub class: String,
23
24 #[serde(rename = "Cgroup")]
26 pub group: String,
27
28 #[serde(rename = "Capiversion")]
30 pub api_version: Option<String>,
31
32 pub exclusive: Option<bool>,
34
35 pub condition: Option<String>,
37
38 #[serde(rename = "licenseSet")]
40 pub license_set: Option<String>,
41
42 pub changelog: Option<String>,
44
45 pub description: Option<String>,
47
48 pub files: Option<ApiFiles>,
50}
51
52#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
53pub struct ApiFiles {
55 #[serde(rename = "file", default)]
57 pub files: Vec<ApiFile>,
58}
59
60#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
61pub struct ApiFile {
65 pub name: String,
67
68 pub category: String,
70
71 pub attr: Option<String>,
73
74 pub condition: Option<String>,
76
77 pub version: Option<String>,
79
80 pub select: Option<String>,
82
83 pub src: Option<String>,
85
86 pub path: Option<String>,
88
89 pub language: Option<String>,
91
92 pub scope: Option<String>,
94
95 pub public: Option<bool>,
97
98 pub projectpath: Option<String>,
100
101 pub copy: Option<String>,
103}
104
105#[cfg(test)]
106mod tests {
107 use crate::apis::{Api, ApiFile, ApiFiles, Apis};
108
109 #[test]
110 fn parse_apis() {
111 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
112<apis>
113 <api Cclass="CMSIS" Cgroup="RTOS2" Capiversion="2.1.3" exclusive="false"
114 condition="ARMCC6" licenseSet="all" changelog="Changelog.txt">
115 <description>CMSIS-RTOS2 API for real-time operating systems</description>
116 <files>
117 <file category="header" name="CMSIS/RTOS2/Include/cmsis_os2.h"/>
118 <file category="doc" name="CMSIS/RTOS2/Doc/index.html" public="true"/>
119 </files>
120 </api>
121 <api Cclass="Device" Cgroup="Startup"/>
122</apis>"#;
123
124 let apis: Apis = serde_roxmltree::from_str(xml_str).unwrap();
125 assert_eq!(apis.apis.len(), 2);
126
127 assert_eq!(
128 apis.apis[0],
129 Api {
130 class: "CMSIS".to_string(),
131 group: "RTOS2".to_string(),
132 api_version: Some("2.1.3".to_string()),
133 exclusive: Some(false),
134 condition: Some("ARMCC6".to_string()),
135 license_set: Some("all".to_string()),
136 changelog: Some("Changelog.txt".to_string()),
137 description: Some("CMSIS-RTOS2 API for real-time operating systems".to_string()),
138 files: Some(ApiFiles {
139 files: vec![
140 ApiFile {
141 name: "CMSIS/RTOS2/Include/cmsis_os2.h".to_string(),
142 category: "header".to_string(),
143 attr: None,
144 condition: None,
145 version: None,
146 select: None,
147 src: None,
148 path: None,
149 language: None,
150 scope: None,
151 public: None,
152 projectpath: None,
153 copy: None,
154 },
155 ApiFile {
156 name: "CMSIS/RTOS2/Doc/index.html".to_string(),
157 category: "doc".to_string(),
158 attr: None,
159 condition: None,
160 version: None,
161 select: None,
162 src: None,
163 path: None,
164 language: None,
165 scope: None,
166 public: Some(true),
167 projectpath: None,
168 copy: None,
169 },
170 ],
171 }),
172 }
173 );
174 assert_eq!(
175 apis.apis[1],
176 Api {
177 class: "Device".to_string(),
178 group: "Startup".to_string(),
179 api_version: None,
180 exclusive: None,
181 condition: None,
182 license_set: None,
183 changelog: None,
184 description: None,
185 files: None,
186 }
187 );
188 }
189
190 #[test]
191 fn parse_api_minimal() {
192 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
193<apis>
194 <api Cclass="Security" Cgroup="mbed TLS"/>
195</apis>"#;
196
197 let apis: Apis = serde_roxmltree::from_str(xml_str).unwrap();
198 assert_eq!(apis.apis.len(), 1);
199
200 let api = &apis.apis[0];
201 assert_eq!(api.class, "Security");
202 assert_eq!(api.group, "mbed TLS");
203 assert_eq!(api.api_version, None);
204 assert_eq!(api.exclusive, None);
205 assert_eq!(api.condition, None);
206 assert_eq!(api.license_set, None);
207 assert_eq!(api.changelog, None);
208 assert_eq!(api.description, None);
209 assert_eq!(api.files, None);
210 }
211
212 #[test]
213 fn parse_api_files() {
214 let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
215<apis>
216 <api Cclass="USB" Cgroup="Core">
217 <files>
218 <file category="header" name="USB/Include/usb_core.h"
219 condition="USB_Cond" version="1.0.0" attr="config"
220 select="USB Core Header" src="USB/Src/usb_core.c"
221 public="false"/>
222 </files>
223 </api>
224</apis>"#;
225
226 let apis: Apis = serde_roxmltree::from_str(xml_str).unwrap();
227 let api = &apis.apis[0];
228
229 assert_eq!(api.class, "USB");
230 assert_eq!(api.group, "Core");
231 assert_eq!(api.description, None);
232
233 let files = api.files.as_ref().unwrap();
234 assert_eq!(files.files.len(), 1);
235
236 let file = &files.files[0];
237 assert_eq!(file.name, "USB/Include/usb_core.h");
238 assert_eq!(file.category, "header");
239 assert_eq!(file.condition, Some("USB_Cond".to_string()));
240 assert_eq!(file.version, Some("1.0.0".to_string()));
241 assert_eq!(file.attr, Some("config".to_string()));
242 assert_eq!(file.select, Some("USB Core Header".to_string()));
243 assert_eq!(file.src, Some("USB/Src/usb_core.c".to_string()));
244 assert_eq!(file.public, Some(false));
245 assert_eq!(file.path, None);
246 assert_eq!(file.language, None);
247 assert_eq!(file.scope, None);
248 assert_eq!(file.projectpath, None);
249 }
250}