use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Generators {
#[serde(rename = "generator")]
pub generators: Vec<Generator>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Generator {
pub id: String,
#[serde(rename = "Gvendor")]
pub generator_vendor: Option<String>,
#[serde(rename = "Gtool")]
pub generator_tool: Option<String>,
#[serde(rename = "Gversion")]
pub generator_version: Option<String>,
pub description: Option<String>,
pub select: Option<Select>,
#[serde(rename = "workingDir")]
pub working_dir: Option<String>,
pub gpdsc: Option<Gpdsc>,
#[serde(default)]
pub exe: Vec<Exe>,
pub eclipse: Option<Eclipse>,
pub web: Option<Web>,
pub project_files: Option<ProjectFiles>,
pub files: Option<Files>,
pub command: Option<String>,
pub arguments: Option<GeneratorArguments>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Select {
#[serde(rename = "Dvendor")]
pub device_vendor: String,
#[serde(rename = "Dname")]
pub device_name: Option<String>,
#[serde(rename = "Dvariant")]
pub device_variant: Option<String>,
#[serde(rename = "Pname")]
pub processor_name: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Gpdsc {
pub name: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Exe {
pub host: Option<String>,
#[serde(rename = "command")]
pub commands: Vec<Command>,
#[serde(rename = "argument")]
pub arguments: Vec<Argument>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Eclipse {
pub plugin: String,
pub class: String,
pub method: String,
#[serde(rename = "argument")]
pub arguments: Vec<EclipseArgument>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Web {
pub url: String,
#[serde(rename = "argument", default)]
pub arguments: Vec<WebArgument>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Command {
pub host: Option<String>,
#[serde(rename = "#content")]
pub command: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Argument {
pub mode: Option<String>,
pub host: Option<String>,
pub switch: Option<String>,
#[serde(rename = "#content")]
pub value: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct WebArgument {
pub switch: String,
#[serde(rename = "#content")]
pub value: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct EclipseArgument {
#[serde(rename = "#content")]
pub value: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct ProjectFiles {
#[serde(rename = "file", default)]
pub files: Vec<ProjectFile>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct Files {
#[serde(rename = "file", default)]
pub files: Vec<File>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct File {
pub name: String,
pub category: String,
pub condition: Option<String>,
pub version: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct ProjectFile {
pub condition: Option<String>,
pub category: String,
pub language: Option<String>,
pub scope: Option<String>,
pub attr: Option<String>,
pub select: Option<String>,
pub name: String,
pub path: Option<String>,
pub copy: Option<String>,
pub version: Option<String>,
pub src: Option<String>,
pub public: Option<bool>,
pub projectpath: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Clone, Default, Deserialize, Serialize)]
pub struct GeneratorArguments {
#[serde(rename = "argument", default)]
pub argument: Vec<String>,
}
#[cfg(test)]
mod tests {
use crate::generators::{
Argument, Command, Eclipse, EclipseArgument, Exe, File, Files, Generators, Gpdsc,
ProjectFile, ProjectFiles, Select, Web, WebArgument,
};
#[test]
fn parse_generators() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<generators>
<generator id="STCubeMX" Gvendor="STMicroelectronics" Gtool="STM32CubeMX" Gversion="6.0.0">
<description>STM32CubeMX code generator</description>
<select Dvendor="STMicroelectronics:13" Dname="STM32*" Pname="Cortex-M4"/>
<workingDir>$P</workingDir>
<gpdsc name="$P/MyProject.gpdsc"/>
<exe>
<command host="win">$S/CubeMX/cubemx.exe</command>
<command host="linux">$S/CubeMX/cubemx</command>
<argument switch="--project">$P</argument>
</exe>
<project_files>
<file name="main.c" category="sourceC"/>
</project_files>
<files>
<file name="cubemx.exe" category="other" condition="Win" version="6.0.0"/>
</files>
</generator>
</generators>"#;
let generators: Generators = serde_roxmltree::from_str(xml_str).unwrap();
assert_eq!(generators.generators.len(), 1);
let generator = &generators.generators[0];
assert_eq!(generator.id, "STCubeMX");
assert_eq!(
generator.generator_vendor,
Some("STMicroelectronics".to_string())
);
assert_eq!(generator.generator_tool, Some("STM32CubeMX".to_string()));
assert_eq!(generator.generator_version, Some("6.0.0".to_string()));
assert_eq!(
generator.description,
Some("STM32CubeMX code generator".to_string())
);
assert_eq!(generator.working_dir, Some("$P".to_string()));
assert_eq!(
generator.select,
Some(Select {
device_vendor: "STMicroelectronics:13".to_string(),
device_name: Some("STM32*".to_string()),
device_variant: None,
processor_name: Some("Cortex-M4".to_string()),
})
);
assert_eq!(
generator.gpdsc,
Some(Gpdsc {
name: "$P/MyProject.gpdsc".to_string()
})
);
assert_eq!(
generator.exe,
vec![Exe {
host: None,
commands: vec![
Command {
host: Some("win".to_string()),
command: "$S/CubeMX/cubemx.exe".to_string()
},
Command {
host: Some("linux".to_string()),
command: "$S/CubeMX/cubemx".to_string()
},
],
arguments: vec![Argument {
mode: None,
host: None,
switch: Some("--project".to_string()),
value: "$P".to_string()
},],
}]
);
assert_eq!(
generator.project_files,
Some(ProjectFiles {
files: vec![ProjectFile {
condition: None,
category: "sourceC".to_string(),
language: None,
scope: None,
attr: None,
select: None,
name: "main.c".to_string(),
path: None,
copy: None,
version: None,
src: None,
public: None,
projectpath: None,
}],
})
);
assert_eq!(
generator.files,
Some(Files {
files: vec![File {
name: "cubemx.exe".to_string(),
category: "other".to_string(),
condition: Some("Win".to_string()),
version: Some("6.0.0".to_string()),
}],
})
);
assert_eq!(generator.eclipse, None);
assert_eq!(generator.web, None);
}
#[test]
fn parse_generator_eclipse() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<generators>
<generator id="MyEclipseGen">
<eclipse plugin="com.example.generator" class="com.example.Generator" method="generate">
<argument>$D</argument>
<argument>--dry-run</argument>
</eclipse>
</generator>
</generators>"#;
let generators: Generators = serde_roxmltree::from_str(xml_str).unwrap();
let generator = &generators.generators[0];
assert_eq!(generator.id, "MyEclipseGen");
assert_eq!(
generator.eclipse,
Some(Eclipse {
plugin: "com.example.generator".to_string(),
class: "com.example.Generator".to_string(),
method: "generate".to_string(),
arguments: vec![
EclipseArgument {
value: "$D".to_string()
},
EclipseArgument {
value: "--dry-run".to_string()
},
],
})
);
assert!(generator.exe.is_empty());
assert_eq!(generator.web, None);
}
#[test]
fn parse_generator_web() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<generators>
<generator id="MyWebGen">
<web url="https://generator.example.com/api">
<argument switch="--board">$B</argument>
</web>
</generator>
</generators>"#;
let generators: Generators = serde_roxmltree::from_str(xml_str).unwrap();
let generator = &generators.generators[0];
assert_eq!(generator.id, "MyWebGen");
assert_eq!(
generator.web,
Some(Web {
url: "https://generator.example.com/api".to_string(),
arguments: vec![WebArgument {
switch: "--board".to_string(),
value: "$B".to_string()
},],
})
);
assert!(generator.exe.is_empty());
assert_eq!(generator.eclipse, None);
}
#[test]
fn parse_generator_deprecated_command_arguments() {
let xml_str = r#"<?xml version="1.0" encoding="UTF-8"?>
<generators>
<generator id="OldStyleGen">
<description>Legacy generator using deprecated command/arguments elements</description>
<command>$S/tools/oldgen</command>
<arguments>
<argument>--project</argument>
<argument>$P</argument>
</arguments>
</generator>
</generators>"#;
let generators: Generators = serde_roxmltree::from_str(xml_str).unwrap();
assert_eq!(generators.generators.len(), 1);
let generator = &generators.generators[0];
assert_eq!(generator.id, "OldStyleGen");
assert_eq!(generator.command, Some("$S/tools/oldgen".to_string()));
let args = generator
.arguments
.as_ref()
.expect("arguments should be present");
assert_eq!(
args.argument,
vec!["--project".to_string(), "$P".to_string(),]
);
assert!(generator.exe.is_empty());
}
}