Skip to content

Commit b14cf64

Browse files
Merge #114
114: feat: `convert`: Add `format_config` option r=adamgreig a=duskmoon314 ## Intro We can use `svdtools convert <input.svd> <output.svd> --format-config <format_config.yaml/json>` to format an SVD file now. For example, we have `.svdfmt.yaml` with the below lines: ```YAML peripheral_name: Constant peripheral_base_address: UpperHex16 ``` The output SVD file will have peripheral names in `CONSTANT_CASE` and addresses like `0x00ABCDEF` or `0x0123456789ABCDEF`. The available config is in [`svd-encoder`](https://github.com/rust-embedded/svd/blob/master/svd-encoder/src/config.rs) Only support SVD output via `svd-encoder` for now. Co-authored-by: Campbell He <[email protected]>
2 parents 664c63d + 431a168 commit b14cf64

File tree

6 files changed

+82
-30
lines changed

6 files changed

+82
-30
lines changed

CHANGELOG-rust.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See
55

66
## [Unreleased]
77

8+
* `convert`: Add `format_config` option
9+
810
## [v0.2.4] 2022-05-15
911

1012
* Added action to build binaries and release for every version tag and latest commit

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ edition = "2021"
2727
clap = { version = "3.0", features = ["derive"] }
2828
serde = { version = "1.0", features = ["derive"] }
2929
quick-xml = { version = "0.18", features = ["serialize"] }
30-
svd-rs = { version = "0.13.2", features = ["serde", "derive-from"] }
31-
svd-parser = { version = "0.13.4", features = ["expand"] }
32-
svd-encoder = "0.13.1"
30+
svd-rs = { version = "0.14.0", features = ["serde", "derive-from"] }
31+
svd-parser = { version = "0.14.0", features = ["expand"] }
32+
svd-encoder = "0.14.0"
3333
yaml-rust = "0.4"
3434
serde_yaml = "0.8.23"
3535
serde_json = { version = "1.0", features = ["preserve_order"] }

src/cli.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ enum Command {
7171
/// Skip enumeratedValues and writeConstraints during parsing (XML input only)
7272
#[clap(long)]
7373
ignore_enums: bool,
74+
75+
/// Path to format config file
76+
///
77+
/// If not specified, the default format config will be used.
78+
///
79+
/// Only used for SVD output format.
80+
#[clap(long = "format-config", parse(from_os_str))]
81+
format_config: Option<PathBuf>,
7482
},
7583
}
7684

@@ -94,14 +102,18 @@ impl Command {
94102
expand,
95103
expand_properties,
96104
ignore_enums,
105+
format_config,
97106
} => convert_cli::convert(
98107
in_path,
99108
out_path,
100109
*input_format,
101110
*output_format,
102-
*expand,
103-
*expand_properties,
104-
*ignore_enums,
111+
convert_cli::ParserConfig {
112+
expand: *expand,
113+
expand_properties: *expand_properties,
114+
ignore_enums: *ignore_enums,
115+
},
116+
format_config.as_ref().map(|p| p.as_path()),
105117
)?,
106118
}
107119
Ok(())

src/convert/convert_cli.rs

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl FromStr for InputFormat {
1818
"svd" | "SVD" | "xml" | "XML" => Ok(Self::Xml),
1919
"yml" | "yaml" | "YAML" => Ok(Self::Yaml),
2020
"json" | "JSON" => Ok(Self::Json),
21-
_ => return Err(anyhow!("Unknown input file format")),
21+
_ => Err(anyhow!("Unknown input file format")),
2222
}
2323
}
2424
}
@@ -38,19 +38,42 @@ impl FromStr for OutputFormat {
3838
"svd" | "SVD" | "xml" | "XML" => Ok(Self::Xml),
3939
"yml" | "yaml" | "YAML" => Ok(Self::Yaml),
4040
"json" | "JSON" => Ok(Self::Json),
41-
_ => return Err(anyhow!("Unknown output file format")),
41+
_ => Err(anyhow!("Unknown output file format")),
4242
}
4343
}
4444
}
4545

46+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47+
#[non_exhaustive]
48+
pub enum ConfigFormat {
49+
Yaml,
50+
Json,
51+
}
52+
53+
impl FromStr for ConfigFormat {
54+
type Err = anyhow::Error;
55+
fn from_str(s: &str) -> Result<Self, Self::Err> {
56+
match s {
57+
"yml" | "yaml" | "YAML" => Ok(Self::Yaml),
58+
"json" | "JSON" => Ok(Self::Json),
59+
_ => Err(anyhow!("Unknown config file format")),
60+
}
61+
}
62+
}
63+
64+
pub struct ParserConfig {
65+
pub expand: bool,
66+
pub expand_properties: bool,
67+
pub ignore_enums: bool,
68+
}
69+
4670
pub fn convert(
4771
in_path: &Path,
4872
out_path: &Path,
4973
input_format: Option<InputFormat>,
5074
output_format: Option<OutputFormat>,
51-
expand: bool,
52-
expand_properties: bool,
53-
ignore_enums: bool,
75+
parser_config: ParserConfig,
76+
format_config: Option<&Path>,
5477
) -> Result<()> {
5578
let input_format = match input_format {
5679
None => match in_path.extension().and_then(|e| e.to_str()) {
@@ -73,22 +96,45 @@ pub fn convert(
7396
let mut device = match input_format {
7497
InputFormat::Xml => svd_parser::parse_with_config(
7598
&input,
76-
&svd_parser::Config::default().ignore_enums(ignore_enums),
99+
&svd_parser::Config::default().ignore_enums(parser_config.ignore_enums),
77100
)?,
78101
InputFormat::Yaml => serde_yaml::from_str(&input)?,
79102
InputFormat::Json => serde_json::from_str(&input)?,
80103
};
81-
if expand_properties {
104+
if parser_config.expand_properties {
82105
svd_parser::expand_properties(&mut device);
83106
}
84-
let device = if expand {
107+
let device = if parser_config.expand {
85108
svd_parser::expand(&device)?
86109
} else {
87110
device
88111
};
89112

113+
let config = if let Some(format_config) = format_config {
114+
let config_format = match format_config.extension().and_then(|e| e.to_str()) {
115+
Some(s) => ConfigFormat::from_str(s)?,
116+
_ => return Err(anyhow!("Unknown output file format")),
117+
};
118+
let mut config = String::new();
119+
File::open(format_config)?.read_to_string(&mut config)?;
120+
121+
let config_map: std::collections::HashMap<String, String> = match config_format {
122+
ConfigFormat::Yaml => serde_yaml::from_str(&config)?,
123+
ConfigFormat::Json => serde_json::from_str(&config)?,
124+
};
125+
126+
let mut config = svd_encoder::Config::default();
127+
config_map
128+
.iter()
129+
.for_each(|(name, value)| config.update(name, value));
130+
131+
config
132+
} else {
133+
svd_encoder::Config::default()
134+
};
135+
90136
let output = match output_format {
91-
OutputFormat::Xml => svd_encoder::encode(&device)?,
137+
OutputFormat::Xml => svd_encoder::encode_with_config(&device, &config)?,
92138
OutputFormat::Yaml => serde_yaml::to_string(&device)?,
93139
OutputFormat::Json => serde_json::to_string_pretty(&device)?,
94140
};

src/patch/device.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,9 @@ pub struct PerIter<'a, 'b> {
1919
impl<'a, 'b> Iterator for PerIter<'a, 'b> {
2020
type Item = &'a mut Peripheral;
2121
fn next(&mut self) -> Option<Self::Item> {
22-
for next in self.it.by_ref() {
23-
if matchname(&next.name, self.spec)
24-
&& !(self.check_derived && next.derived_from.is_some())
25-
{
26-
return Some(next);
27-
}
28-
}
29-
None
22+
self.it.by_ref().find(|next| {
23+
matchname(&next.name, self.spec) && !(self.check_derived && next.derived_from.is_some())
24+
})
3025
}
3126
}
3227

src/patch/iterators.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@ where
1818
{
1919
type Item = I::Item;
2020
fn next(&mut self) -> Option<Self::Item> {
21-
for next in self.it.by_ref() {
22-
if matchname(next.name(), self.spec) {
23-
return Some(next);
24-
}
25-
}
26-
None
21+
self.it
22+
.by_ref()
23+
.find(|next| matchname(next.name(), self.spec))
2724
}
2825
}
2926

@@ -60,7 +57,7 @@ where
6057
}
6158
}
6259

63-
impl<'a, I> Iterator for OptIter<I>
60+
impl<I> Iterator for OptIter<I>
6461
where
6562
I: Iterator,
6663
{

0 commit comments

Comments
 (0)