Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See

## [Unreleased]

* `convert`: Add `format_config` option

## [v0.2.4] 2022-05-15

* Added action to build binaries and release for every version tag and latest commit
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ edition = "2021"
clap = { version = "3.0", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
quick-xml = { version = "0.18", features = ["serialize"] }
svd-rs = { version = "0.13.2", features = ["serde", "derive-from"] }
svd-parser = { version = "0.13.4", features = ["expand"] }
svd-encoder = "0.13.1"
svd-rs = { version = "0.14.0", features = ["serde", "derive-from"] }
svd-parser = { version = "0.14.0", features = ["expand"] }
svd-encoder = "0.14.0"
yaml-rust = "0.4"
serde_yaml = "0.8.23"
serde_json = { version = "1.0", features = ["preserve_order"] }
Expand Down
18 changes: 15 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ enum Command {
/// Skip enumeratedValues and writeConstraints during parsing (XML input only)
#[clap(long)]
ignore_enums: bool,

/// Path to format config file
///
/// If not specified, the default format config will be used.
///
/// Only used for SVD output format.
#[clap(long = "format-config", parse(from_os_str))]
format_config: Option<PathBuf>,
},
}

Expand All @@ -94,14 +102,18 @@ impl Command {
expand,
expand_properties,
ignore_enums,
format_config,
} => convert_cli::convert(
in_path,
out_path,
*input_format,
*output_format,
*expand,
*expand_properties,
*ignore_enums,
convert_cli::ParserConfig {
expand: *expand,
expand_properties: *expand_properties,
ignore_enums: *ignore_enums,
},
format_config.as_ref().map(|p| p.as_path()),
)?,
}
Ok(())
Expand Down
64 changes: 55 additions & 9 deletions src/convert/convert_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl FromStr for InputFormat {
"svd" | "SVD" | "xml" | "XML" => Ok(Self::Xml),
"yml" | "yaml" | "YAML" => Ok(Self::Yaml),
"json" | "JSON" => Ok(Self::Json),
_ => return Err(anyhow!("Unknown input file format")),
_ => Err(anyhow!("Unknown input file format")),
}
}
}
Expand All @@ -38,19 +38,42 @@ impl FromStr for OutputFormat {
"svd" | "SVD" | "xml" | "XML" => Ok(Self::Xml),
"yml" | "yaml" | "YAML" => Ok(Self::Yaml),
"json" | "JSON" => Ok(Self::Json),
_ => return Err(anyhow!("Unknown output file format")),
_ => Err(anyhow!("Unknown output file format")),
}
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum ConfigFormat {
Yaml,
Json,
}

impl FromStr for ConfigFormat {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"yml" | "yaml" | "YAML" => Ok(Self::Yaml),
"json" | "JSON" => Ok(Self::Json),
_ => Err(anyhow!("Unknown config file format")),
}
}
}

pub struct ParserConfig {
pub expand: bool,
pub expand_properties: bool,
pub ignore_enums: bool,
}

pub fn convert(
in_path: &Path,
out_path: &Path,
input_format: Option<InputFormat>,
output_format: Option<OutputFormat>,
expand: bool,
expand_properties: bool,
ignore_enums: bool,
parser_config: ParserConfig,
format_config: Option<&Path>,
) -> Result<()> {
let input_format = match input_format {
None => match in_path.extension().and_then(|e| e.to_str()) {
Expand All @@ -73,22 +96,45 @@ pub fn convert(
let mut device = match input_format {
InputFormat::Xml => svd_parser::parse_with_config(
&input,
&svd_parser::Config::default().ignore_enums(ignore_enums),
&svd_parser::Config::default().ignore_enums(parser_config.ignore_enums),
)?,
InputFormat::Yaml => serde_yaml::from_str(&input)?,
InputFormat::Json => serde_json::from_str(&input)?,
};
if expand_properties {
if parser_config.expand_properties {
svd_parser::expand_properties(&mut device);
}
let device = if expand {
let device = if parser_config.expand {
svd_parser::expand(&device)?
} else {
device
};

let config = if let Some(format_config) = format_config {
let config_format = match format_config.extension().and_then(|e| e.to_str()) {
Some(s) => ConfigFormat::from_str(s)?,
_ => return Err(anyhow!("Unknown output file format")),
};
let mut config = String::new();
File::open(format_config)?.read_to_string(&mut config)?;

let config_map: std::collections::HashMap<String, String> = match config_format {
ConfigFormat::Yaml => serde_yaml::from_str(&config)?,
ConfigFormat::Json => serde_json::from_str(&config)?,
};

let mut config = svd_encoder::Config::default();
config_map
.iter()
.for_each(|(name, value)| config.update(name, value));

config
} else {
svd_encoder::Config::default()
};

let output = match output_format {
OutputFormat::Xml => svd_encoder::encode(&device)?,
OutputFormat::Xml => svd_encoder::encode_with_config(&device, &config)?,
OutputFormat::Yaml => serde_yaml::to_string(&device)?,
OutputFormat::Json => serde_json::to_string_pretty(&device)?,
};
Expand Down
11 changes: 3 additions & 8 deletions src/patch/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,9 @@ pub struct PerIter<'a, 'b> {
impl<'a, 'b> Iterator for PerIter<'a, 'b> {
type Item = &'a mut Peripheral;
fn next(&mut self) -> Option<Self::Item> {
for next in self.it.by_ref() {
if matchname(&next.name, self.spec)
&& !(self.check_derived && next.derived_from.is_some())
{
return Some(next);
}
}
None
self.it.by_ref().find(|next| {
matchname(&next.name, self.spec) && !(self.check_derived && next.derived_from.is_some())
})
}
}

Expand Down
11 changes: 4 additions & 7 deletions src/patch/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@ where
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
for next in self.it.by_ref() {
if matchname(next.name(), self.spec) {
return Some(next);
}
}
None
self.it
.by_ref()
.find(|next| matchname(next.name(), self.spec))
}
}

Expand Down Expand Up @@ -60,7 +57,7 @@ where
}
}

impl<'a, I> Iterator for OptIter<I>
impl<I> Iterator for OptIter<I>
where
I: Iterator,
{
Expand Down