Skip to main content

cmsis_pdsc_parser/
csolution.rs

1//! Contains the types required to represent a [PDSC csolution](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/pdsc_csolution_pg.html#element_csolution) element
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
6/// Represents the [PDSC csolution](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/pdsc_csolution_pg.html#element_csolution) element
7///
8/// Groups software layers and project templates published by a pack for use with csolution-based projects.
9pub struct Csolution {
10    /// Software layer definitions (0..*)
11    #[serde(rename = "clayer", default)]
12    pub clayers: Vec<Clayer>,
13
14    /// Project template definitions (0..*)
15    #[serde(rename = "template", default)]
16    pub templates: Vec<CsolutionTemplate>,
17}
18
19#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
20/// Represents a [clayer](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/pdsc_csolution_pg.html#element_clayer) element
21///
22/// Provides access information for a software layer stored in a pack.
23pub struct Clayer {
24    /// Layer type identifier
25    #[serde(rename = "type")]
26    pub layer_type: String,
27
28    /// Path to the layer directory relative to the pack root
29    pub path: String,
30
31    /// Layer project file name (e.g. `.clayer.yml`)
32    pub file: String,
33
34    /// Optional destination path when copying the layer into a project
35    #[serde(rename = "copy-to")]
36    pub copy_to: Option<String>,
37
38    /// References a condition ID; layer is available only if the condition is met
39    pub condition: Option<String>,
40
41    /// Text content of the element
42    #[serde(rename = "#content")]
43    pub content: String,
44}
45
46#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
47/// Represents a [template](https://open-cmsis-pack.github.io/Open-CMSIS-Pack-Spec/main/html/pdsc_csolution_pg.html#element_cs_template) element
48///
49/// Defines a project template for initialising new csolution projects in an IDE.
50pub struct CsolutionTemplate {
51    /// Template display name
52    pub name: String,
53
54    /// Path to the template directory relative to the pack root
55    pub path: String,
56
57    /// Template project file name (e.g. `.csolution.yml`)
58    pub file: String,
59
60    /// Optional destination path when copying the template into a project
61    #[serde(rename = "copy-to")]
62    pub copy_to: Option<String>,
63
64    /// References a condition ID; template is available only if the condition is met
65    pub condition: Option<String>,
66
67    /// Brief description of the template
68    pub description: String,
69}
70
71#[cfg(test)]
72mod tests {
73    use crate::csolution::{Clayer, Csolution, CsolutionTemplate};
74
75    #[test]
76    fn parse_csolution() {
77        let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
78<csolution>
79    <clayer type="Board" path="layers/board" file="Board.clayer.yml"
80            copy-to="Board" condition="CM4">Board layer description</clayer>
81    <clayer type="Shield" path="layers/shield" file="Shield.clayer.yml"/>
82    <template name="Blinky" path="templates/Blinky" file="Blinky.csolution.yml"
83              copy-to="MyBlinky" condition="GCC">
84        <description>Simple LED blinking template</description>
85    </template>
86    <template name="Empty" path="templates/Empty" file="Empty.csolution.yml">
87        <description>Minimal empty project</description>
88    </template>
89</csolution>"#;
90
91        let cs: Csolution = serde_roxmltree::from_str(xml_str).unwrap();
92
93        assert_eq!(cs.clayers.len(), 2);
94        assert_eq!(
95            cs.clayers[0],
96            Clayer {
97                layer_type: "Board".to_string(),
98                path: "layers/board".to_string(),
99                file: "Board.clayer.yml".to_string(),
100                copy_to: Some("Board".to_string()),
101                condition: Some("CM4".to_string()),
102                content: "Board layer description".to_string(),
103            }
104        );
105        assert_eq!(
106            cs.clayers[1],
107            Clayer {
108                layer_type: "Shield".to_string(),
109                path: "layers/shield".to_string(),
110                file: "Shield.clayer.yml".to_string(),
111                copy_to: None,
112                condition: None,
113                content: String::new(),
114            }
115        );
116
117        assert_eq!(cs.templates.len(), 2);
118        assert_eq!(
119            cs.templates[0],
120            CsolutionTemplate {
121                name: "Blinky".to_string(),
122                path: "templates/Blinky".to_string(),
123                file: "Blinky.csolution.yml".to_string(),
124                copy_to: Some("MyBlinky".to_string()),
125                condition: Some("GCC".to_string()),
126                description: "Simple LED blinking template".to_string(),
127            }
128        );
129        assert_eq!(
130            cs.templates[1],
131            CsolutionTemplate {
132                name: "Empty".to_string(),
133                path: "templates/Empty".to_string(),
134                file: "Empty.csolution.yml".to_string(),
135                copy_to: None,
136                condition: None,
137                description: "Minimal empty project".to_string(),
138            }
139        );
140    }
141
142    #[test]
143    fn parse_csolution_clayers_only() {
144        let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
145<csolution>
146    <clayer type="App" path="layers/app" file="App.clayer.yml"/>
147</csolution>"#;
148
149        let cs: Csolution = serde_roxmltree::from_str(xml_str).unwrap();
150        assert_eq!(cs.clayers.len(), 1);
151        assert_eq!(cs.templates.len(), 0);
152
153        let l = &cs.clayers[0];
154        assert_eq!(l.layer_type, "App");
155        assert_eq!(l.path, "layers/app");
156        assert_eq!(l.file, "App.clayer.yml");
157        assert_eq!(l.copy_to, None);
158        assert_eq!(l.condition, None);
159    }
160
161    #[test]
162    fn parse_csolution_templates_only() {
163        let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
164<csolution>
165    <template name="Full" path="templates/Full" file="Full.csolution.yml"
166              copy-to="MyProject">
167        <description>Full-featured project template</description>
168    </template>
169</csolution>"#;
170
171        let cs: Csolution = serde_roxmltree::from_str(xml_str).unwrap();
172        assert_eq!(cs.clayers.len(), 0);
173        assert_eq!(cs.templates.len(), 1);
174
175        let t = &cs.templates[0];
176        assert_eq!(t.name, "Full");
177        assert_eq!(t.path, "templates/Full");
178        assert_eq!(t.file, "Full.csolution.yml");
179        assert_eq!(t.copy_to, Some("MyProject".to_string()));
180        assert_eq!(t.condition, None);
181        assert_eq!(t.description, "Full-featured project template");
182    }
183}