cmsis_pack/pack_index/
mod.rs

1use crate::utils::prelude::*;
2use anyhow::Error;
3use roxmltree::Node;
4
5#[derive(Debug, Clone)]
6pub struct PdscRef {
7    pub url: String,
8    pub vendor: String,
9    pub name: String,
10    pub version: String,
11    pub date: Option<String>,
12    pub deprecated: Option<String>,
13    pub replacement: Option<String>,
14    pub size: Option<String>,
15}
16
17#[derive(Debug)]
18pub struct Pidx {
19    pub url: String,
20    pub vendor: String,
21    pub date: Option<String>,
22}
23
24#[derive(Debug)]
25pub struct Vidx {
26    pub vendor: String,
27    pub url: String,
28    pub timestamp: Option<String>,
29    pub pdsc_index: Vec<PdscRef>,
30    pub vendor_index: Vec<Pidx>,
31}
32
33impl FromElem for PdscRef {
34    fn from_elem(e: &Node) -> Result<Self, Error> {
35        assert_root_name(e, "pdsc")?;
36        Ok(Self {
37            url: attr_map(e, "url")?,
38            vendor: attr_map(e, "vendor")?,
39            name: attr_map(e, "name")?,
40            version: attr_map(e, "version")?,
41            date: attr_map(e, "date").ok(),
42            deprecated: attr_map(e, "deprecated").ok(),
43            replacement: attr_map(e, "replacement").ok(),
44            size: attr_map(e, "size").ok(),
45        })
46    }
47}
48
49impl FromElem for Pidx {
50    fn from_elem(e: &Node) -> Result<Self, Error> {
51        assert_root_name(e, "pidx")?;
52        Ok(Self {
53            url: attr_map(e, "url")?,
54            vendor: attr_map(e, "vendor")?,
55            date: attr_map(e, "date").ok(),
56        })
57    }
58}
59
60impl FromElem for Vidx {
61    fn from_elem(root: &Node) -> Result<Self, Error> {
62        assert_root_name(root, "index")?;
63        let vendor = child_text(root, "vendor")?;
64        let url = child_text(root, "url")?;
65
66        let mut timestamp: Option<String> = None;
67        let mut vendor_index: Vec<Pidx> = Vec::new();
68        let mut pdsc_index: Vec<PdscRef> = Vec::new();
69        for child in root.children() {
70            match child.tag_name().name() {
71                "timestamp" => {
72                    timestamp = Some(child).map(|e| e.text().unwrap_or_default().to_string())
73                }
74                "vindex" => {
75                    vendor_index = Pidx::vec_from_children(child.children());
76                }
77                "pindex" => {
78                    pdsc_index = PdscRef::vec_from_children(child.children());
79                }
80                _ => continue,
81            }
82        }
83
84        Ok(Vidx {
85            vendor,
86            url,
87            timestamp,
88            vendor_index,
89            pdsc_index,
90        })
91    }
92}
93
94#[cfg(test)]
95mod test {
96    use super::*;
97
98    #[test]
99    fn pdscref_missing_attr() {
100        let erroring_strings = vec![
101            "<pdsc>",
102            "<pdsc url=\"Vendor\" name=\"Name\" version=\"1.2.3-alpha\">",
103            "<pdsc vendor=\"Vendor\" url=\"Url\" version=\"1.2.3-alpha\">",
104            "<pdsc vendor=\"Vendor\" name=\"Name\" url=\"Url\">",
105            "<pdsc vendor=\"Vendor\" name=\"Name\" version=\"1.2.3-alpha\">",
106        ];
107        for bad_string in erroring_strings {
108            assert!(PdscRef::from_string(bad_string).is_err());
109        }
110    }
111
112    #[test]
113    fn pdscref_wrong_elem() {
114        let bad_string =
115            "<notPdsc vendor=\"Vendor\" url=\"Url\" name=\"name\" version=\"1.2.3-alpha\">";
116        assert!(PdscRef::from_string(bad_string).is_err())
117    }
118
119    #[test]
120    fn pdscref_optionals() {
121        let good_string =
122            "<pdsc vendor=\"Vendor\" url=\"Url\" name=\"Name\" version=\"1.2.3-alpha\">";
123        let response = PdscRef::from_string(good_string).unwrap();
124        assert_eq!(response.vendor, String::from("Vendor"));
125        assert_eq!(response.url, "Url");
126        assert_eq!(response.name, String::from("Name"));
127        assert_eq!(response.version, String::from("1.2.3-alpha"));
128        let good_string =
129            "<pdsc vendor=\"Vendor\" url=\"Url\" name=\"Name\" version=\"1.2.3-alpha\"
130                date=\"A-Date\" deprecated=\"true\" replacement=\"Other\" size=\"8MB\">";
131        let response = PdscRef::from_string(good_string).unwrap();
132        assert_eq!(response.date, Some(String::from("A-Date")));
133        assert_eq!(response.deprecated, Some(String::from("true")));
134        assert_eq!(response.replacement, Some(String::from("Other")));
135        assert_eq!(response.size, Some(String::from("8MB")));
136    }
137
138    #[test]
139    fn pidx_misssing_attr() {
140        let erroring_strings = vec![
141            "<pidx/>",
142            "<pidx vendor=\"Vendor\"/>",
143            "<pidx url=\"Url\"/>",
144        ];
145        for bad_string in erroring_strings {
146            assert!(Pidx::from_string(bad_string).is_err());
147        }
148    }
149
150    #[test]
151    fn pidx_wrong_elem() {
152        let bad_string = "<notpidx url=\"Url\" vendor=\"Vendor\"/>";
153        assert!(Pidx::from_string(bad_string).is_err())
154    }
155
156    #[test]
157    fn pidx_optionals() {
158        let good_string = "<pidx vendor=\"Vendor\" url=\"Url\"/>";
159        let response = Pidx::from_string(good_string).unwrap();
160        assert_eq!(response.vendor, String::from("Vendor"));
161        assert_eq!(response.url, "Url");
162
163        let good_string =
164            "<pidx vendor=\"Vendor\" url=\"Url\" date=\"Fri Sep  1 11:21:06 CDT 2017\"/>";
165        let response = Pidx::from_string(good_string).unwrap();
166        assert_eq!(response.vendor, String::from("Vendor"));
167        assert_eq!(response.url, "Url");
168        assert_eq!(
169            response.date,
170            Some(String::from("Fri Sep  1 11:21:06 CDT 2017"))
171        )
172    }
173
174    #[test]
175    fn vidx_misssing_attr() {
176        let erroring_strings = vec![
177            "<index xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\">
178             </index>",
179            "<index xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\">
180               <vendor>Vendor</vendor>
181             </index>",
182            "<index xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\">
183               <url>Url</url>
184             </index>",
185        ];
186        for bad_string in erroring_strings {
187            assert!(Vidx::from_string(bad_string).is_err());
188        }
189    }
190
191    #[test]
192    fn vidx_wrong_elem() {
193        let bad_string = "<notindex xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\">
194               <vendor>Vendor</vendor>
195               <url>Url</url>
196             </notindex>";
197        assert!(Vidx::from_string(bad_string).is_err())
198    }
199
200    #[test]
201    fn vidx_optionals() {
202        let good_string = "<index xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\">
203               <vendor>Vendor</vendor>
204               <url>Url</url>
205             </index>";
206        let response = Vidx::from_string(good_string).unwrap();
207        assert_eq!(response.vendor, String::from("Vendor"));
208        assert_eq!(response.url, "Url");
209
210        let good_string = "<index xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\">
211               <vendor>Vendor</vendor>
212               <url>Url</url>
213               <timestamp>Fri Sep  1 13:26:41 CDT 2017</timestamp>
214             </index>";
215        let response = Vidx::from_string(good_string).unwrap();
216        assert_eq!(response.vendor, String::from("Vendor"));
217        assert_eq!(response.url, "Url");
218        assert_eq!(
219            response.timestamp,
220            Some(String::from("Fri Sep  1 13:26:41 CDT"))
221        );
222    }
223}