1extern crate serde;
4
5use serde::Deserialize;
7
8use crate::Error;
9
10#[derive(Debug, Deserialize, PartialEq)]
16pub struct Mesh {
17 #[serde(rename = "class", default)]
18 pub classes: Vec<Class>,
19}
20
21#[derive(Debug, Deserialize, PartialEq)]
24pub struct Class {
25 pub id: String, pub name: String,
30 #[serde(rename = "geom", default)]
31 pub geoms: Vec<Geom>,
32 }
34
35#[derive(Debug, Deserialize, PartialEq)]
45pub struct Geom {
46 pub id: String, #[serde(rename = "class")]
48 pub class_ref: ClassRef,
49 pub name: String,
50 pub rank: u64,
51 pub config: Option<GeomConfig>,
52 #[serde(rename = "consumer", default)]
53 pub consumers: Vec<Consumer>,
54 #[serde(rename = "provider", default)]
55 pub providers: Vec<Provider>,
56}
57
58#[derive(Debug, Deserialize, PartialEq)]
62pub struct ClassRef {
63 #[serde(rename = "ref")]
64 pub ref_: String, }
66
67#[derive(Debug, Deserialize, PartialEq)]
71pub struct GeomConfig {
72 pub scheme: Option<String>,
74 pub entries: Option<u64>,
75 pub first: Option<u64>,
76 pub last: Option<u64>,
77 pub fwsectors: Option<u64>,
78 pub fwheads: Option<u64>,
79 pub state: Option<String>, pub modified: Option<bool>,
81}
82
83#[derive(Debug, Deserialize, PartialEq)]
90pub struct Consumer {
91 pub id: String, #[serde(rename = "geom")]
93 pub geom_ref: GeomRef,
94 #[serde(rename = "provider")]
95 pub provider_ref: ProviderRef,
96 pub mode: String,
97}
98
99#[derive(Debug, Deserialize, PartialEq)]
105pub struct Provider {
106 pub id: String, #[serde(rename = "geom")]
108 pub geom_ref: GeomRef,
109 pub mode: String,
110 pub name: String,
111 pub mediasize: u64,
112 pub sectorsize: u64,
113 pub stripesize: u64,
114 pub stripeoffset: u64,
115 pub config: ProviderConfig,
116}
117
118#[derive(Debug, Deserialize, PartialEq)]
124pub struct ProviderConfig {
125 pub fwheads: Option<u64>,
127 pub fwsectors: Option<u64>,
128 pub rotationrate: Option<String>,
129 pub ident: Option<String>,
130 pub lunid: Option<String>,
131 pub descr: Option<String>,
132 pub start: Option<u64>,
134 pub end: Option<u64>,
135 pub index: Option<u64>,
136 #[serde(rename = "type")]
137 pub type_: Option<String>,
138 pub offset: Option<u64>,
139 pub length: Option<u64>,
140 pub label: Option<String>,
141 pub rawtype: Option<String>,
142 pub rawuuid: Option<String>,
143 pub efimedia: Option<String>,
144 pub seclength: Option<u64>,
147 pub secoffset: Option<u64>,
148}
149
150#[derive(Debug, Deserialize, PartialEq)]
154pub struct GeomRef {
155 #[serde(rename = "ref")]
156 pub ref_: String, }
158
159#[derive(Debug, Deserialize, PartialEq)]
163pub struct ProviderRef {
164 #[serde(rename = "ref")]
165 pub ref_: String, }
167
168pub fn parse_xml(xml: &str) -> Result<Mesh, Error> {
184 return Ok(quick_xml::de::from_str::<Mesh>(xml)?);
185}
186
187#[cfg(target_os = "freebsd")]
209pub fn get_mesh() -> Result<Mesh, Error> {
210 let xml = crate::get_confxml()?;
211 return Ok(parse_xml(&xml)?);
212}
213
214#[cfg(test)]
215mod tests {
216 use crate::structs;
217
218 #[test]
219 fn xml_mesh_basic() {
220 let xml = "<mesh></mesh>";
221 quick_xml::de::from_str::<structs::Mesh>(xml).unwrap();
222 }
223
224 #[test]
225 fn xml_class_basic() {
226 let xml = "<class id=\"0xffffffff81234567\"><name>FD</name></class>";
227 let cls = quick_xml::de::from_str::<structs::Class>(xml).unwrap();
228 assert_eq!(cls.id, "0xffffffff81234567");
229 assert_eq!(cls.name, "FD");
230 }
231
232 #[test]
233 fn xml_references() {
234 let xml = "<class ref=\"0x123\"/>";
235 let cls = quick_xml::de::from_str::<structs::ClassRef>(xml).unwrap();
236 assert_eq!(cls.ref_, "0x123");
237
238 let xml = "<provider ref=\"0x123\"/>";
239 let p = quick_xml::de::from_str::<structs::ProviderRef>(xml).unwrap();
240 assert_eq!(p.ref_, "0x123");
241
242 let xml = "<geom ref=\"0x123\"/>";
243 let p = quick_xml::de::from_str::<structs::GeomRef>(xml).unwrap();
244 assert_eq!(p.ref_, "0x123");
245 }
246
247 #[test]
248 fn xml_geom_config() {
249 let xml = r#"<config><scheme>GPT</scheme></config>"#;
250 let p = quick_xml::de::from_str::<structs::GeomConfig>(xml).unwrap();
251 assert_eq!(p.scheme.unwrap(), "GPT");
252 }
253
254 #[test]
255 fn xml_consumer() {
256 let xml = r#"<consumer id="0x123">
257 <geom ref="0x456"/>
258 <provider ref="0x789"/>
259 <mode>r0w0e0</mode>
260 </consumer>"#;
261 let p = quick_xml::de::from_str::<structs::Consumer>(xml).unwrap();
262 assert_eq!(
263 p,
264 structs::Consumer {
265 id: "0x123".into(),
266 geom_ref: structs::GeomRef {
267 ref_: "0x456".into()
268 },
269 provider_ref: structs::ProviderRef {
270 ref_: "0x789".into()
271 },
272 mode: "r0w0e0".into(),
273 }
274 );
275 }
276
277 #[test]
278 fn xml_provider_config() {
279 let xml = r#"<config>
281 <fwheads>1</fwheads>
282 <fwsectors>2</fwsectors>
283 <rotationrate>0</rotationrate>
284 <ident>S3Z</ident>
285 <lunid>00123abcd</lunid>
286 <descr>Samsung SSD</descr>
287 </config>"#;
288 let p = quick_xml::de::from_str::<structs::ProviderConfig>(xml).unwrap();
289 assert_eq!(
290 p,
291 structs::ProviderConfig {
292 fwheads: Some(1),
293 fwsectors: Some(2),
294 rotationrate: Some("0".into()),
295 ident: Some("S3Z".into()),
296 lunid: Some("00123abcd".into()),
297 descr: Some("Samsung SSD".into()),
298 start: None,
300 end: None,
301 index: None,
302 type_: None,
303 offset: None,
304 length: None,
305 label: None,
306 rawtype: None,
307 rawuuid: None,
308 efimedia: None,
309 seclength: None,
311 secoffset: None,
312 }
313 );
314 }
315
316 #[test]
317 fn xml_provider() {
318 let xml = r#"<provider id="0x123">
319 <geom ref="0x456"/>
320 <mode>r1w1e3</mode>
321 <name>ada0</name>
322 <mediasize>10</mediasize>
323 <sectorsize>2</sectorsize>
324 <stripesize>0</stripesize>
325 <stripeoffset>123</stripeoffset>
326 <config>
327 <fwheads>1</fwheads>
328 <fwsectors>2</fwsectors>
329 <rotationrate>0</rotationrate>
330 <ident>S3Z</ident>
331 <lunid>00123abcd</lunid>
332 <descr>Samsung SSD</descr>
333 </config>
334 </provider>"#;
335 let p = quick_xml::de::from_str::<structs::Provider>(xml).unwrap();
336 assert_eq!(p.id, "0x123");
337 assert_eq!(
338 p.geom_ref,
339 structs::GeomRef {
340 ref_: "0x456".into()
341 }
342 );
343 assert_eq!(p.mode, "r1w1e3");
344 assert_eq!(p.name, "ada0");
345 assert_eq!(p.mediasize, 10);
346 assert_eq!(p.sectorsize, 2);
347 assert_eq!(p.stripesize, 0);
348 assert_eq!(p.stripeoffset, 123);
349 }
350
351 #[test]
352 fn xml_geom_basic() {
353 let xml = r#"<geom id="0x123">
354 <class ref="0x456"/>
355 <name>ada0</name>
356 <rank>1</rank>
357 <config>
358 </config>
359 </geom>"#;
360 let p = quick_xml::de::from_str::<structs::Geom>(xml).unwrap();
361 assert_eq!(
362 p,
363 structs::Geom {
364 id: "0x123".into(),
365 class_ref: structs::ClassRef {
366 ref_: "0x456".into()
367 },
368 name: "ada0".into(),
369 rank: 1,
370 config: Some(structs::GeomConfig {
371 scheme: None,
372 entries: None,
373 first: None,
374 last: None,
375 fwsectors: None,
376 fwheads: None,
377 state: None,
378 modified: None,
379 }),
380 consumers: vec![],
381 providers: vec![],
382 }
383 );
384 }
385
386 #[test]
387 fn xml_full_sample() {
388 let xml = include_str!("test/fullsample.xml");
389 let p = quick_xml::de::from_str::<structs::Mesh>(xml).unwrap();
390
391 assert_eq!(p.classes[0].name, "FD");
393 assert_eq!(p.classes[1].name, "RAID");
394
395 assert_eq!(p.classes[2].name, "DISK");
396 assert_eq!(p.classes[2].id, p.classes[2].geoms[0].class_ref.ref_);
397 assert_eq!(
398 p.classes[2].geoms[0].id,
399 p.classes[2].geoms[0].providers[0].geom_ref.ref_
400 );
401 assert_eq!(p.classes[2].geoms[0].providers[0].mediasize, 1000204886016);
402 assert_eq!(
403 p.classes[2].geoms[0].providers[0]
404 .config
405 .lunid
406 .as_ref()
407 .unwrap(),
408 "YYYYYYYYYYYYYYYY"
409 );
410 assert_eq!(p.classes[2].geoms[1].name, "nvd1");
411
412 assert_eq!(p.classes[3].name, "DEV");
413 assert_eq!(p.classes[3].id, p.classes[3].geoms[0].class_ref.ref_);
414 assert_eq!(p.classes[3].geoms[1].name, "ada0p1");
415
416 assert_eq!(
418 p.classes[3].geoms[1].consumers[0].provider_ref.ref_,
419 p.classes[4].geoms[0].providers[0].id
420 );
421
422 assert_eq!(p.classes[4].name, "PART");
423 assert_eq!(p.classes[5].name, "LABEL");
424 assert_eq!(p.classes[6].name, "VFS");
425 assert_eq!(p.classes[7].name, "SWAP");
426 assert_eq!(p.classes[8].name, "Flashmap");
427 assert_eq!(p.classes[9].name, "MD");
428 }
429}