diff --git a/src/common/input_format.rs b/src/common/input_format.rs new file mode 100644 index 00000000..5add0532 --- /dev/null +++ b/src/common/input_format.rs @@ -0,0 +1,26 @@ +use anyhow::{anyhow, Result}; +use std::str::FromStr; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum InputFormat { + Xml, + #[cfg(feature = "yaml")] + Yaml, + #[cfg(feature = "json")] + Json, +} + +impl FromStr for InputFormat { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result { + match s { + "svd" | "SVD" | "xml" | "XML" => Ok(Self::Xml), + #[cfg(feature = "yaml")] + "yml" | "yaml" | "YAML" => Ok(Self::Yaml), + #[cfg(feature = "json")] + "json" | "JSON" => Ok(Self::Json), + _ => Err(anyhow!("Unknown input file format")), + } + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index 3491f0b5..de629a45 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,3 +1,4 @@ +pub mod input_format; pub mod str_utils; pub mod svd_reader; pub mod svd_utils; diff --git a/src/convert/convert_cli.rs b/src/convert/convert_cli.rs index 11ae4b3e..5165bb76 100644 --- a/src/convert/convert_cli.rs +++ b/src/convert/convert_cli.rs @@ -4,33 +4,10 @@ use std::str::FromStr; use std::{fs::File, path::Path}; use svd_rs::Device; +pub use crate::common::input_format::InputFormat; use crate::get_encoder_config; pub use crate::ConfigFormat; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[non_exhaustive] -pub enum InputFormat { - Xml, - #[cfg(feature = "yaml")] - Yaml, - #[cfg(feature = "json")] - Json, -} - -impl FromStr for InputFormat { - type Err = anyhow::Error; - fn from_str(s: &str) -> Result { - match s { - "svd" | "SVD" | "xml" | "XML" => Ok(Self::Xml), - #[cfg(feature = "yaml")] - "yml" | "yaml" | "YAML" => Ok(Self::Yaml), - #[cfg(feature = "json")] - "json" | "JSON" => Ok(Self::Json), - _ => Err(anyhow!("Unknown input file format")), - } - } -} - #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum OutputFormat { diff --git a/src/patch/device.rs b/src/patch/device.rs index e7a3cb1d..e9fb9a82 100644 --- a/src/patch/device.rs +++ b/src/patch/device.rs @@ -4,7 +4,8 @@ use svd_parser::svd::{Device, Peripheral, PeripheralInfo}; use yaml_rust::{yaml::Hash, Yaml}; use std::collections::HashSet; -use std::{fs::File, io::Read, path::Path}; +use std::str::FromStr; +use std::{fs, path::Path}; use super::iterators::{MatchIter, Matched}; use super::peripheral::{PeripheralExt, RegisterBlockExt}; @@ -12,6 +13,7 @@ use super::yaml_ext::{AsType, GetVal}; use super::{abspath, adding_pos, matchname, Config, PatchResult, Spec, VAL_LVL}; use super::{make_address_block, make_address_blocks, make_cpu, make_interrupt, make_peripheral}; use super::{make_dim_element, modify_dim_element, modify_register_properties}; +use crate::common::input_format::InputFormat; pub type PerMatchIterMut<'a, 'b> = MatchIter<'b, std::slice::IterMut<'a, Peripheral>>; @@ -195,11 +197,24 @@ impl DeviceExt for Device { .collect::>(); let mut new = match pcopysrc.as_slice() { [ppath, pcopyname] => { - let f = File::open(abspath(path, Path::new(ppath))?)?; - let mut contents = String::new(); - (&f).read_to_string(&mut contents).unwrap(); - let filedev = svd_parser::parse(&contents) - .with_context(|| format!("Parsing file {contents}"))?; + let ppath = Path::new(ppath); + let input_format = ppath + .extension() + .map(|ext_os| ext_os.to_str().expect("ppath is str")) + .and_then(|ext| InputFormat::from_str(ext).ok()) + .unwrap_or(InputFormat::Xml); + let filepath = abspath(path, ppath)?; + let contents = fs::read_to_string(filepath)?; + let filedev = match input_format { + InputFormat::Xml => svd_parser::parse(&contents) + .with_context(|| format!("Parsing svd file {contents}"))?, + #[cfg(feature = "yaml")] + InputFormat::Yaml => serde_yaml::from_str(&contents) + .with_context(|| format!("Parsing yaml file {contents}"))?, + #[cfg(feature = "json")] + InputFormat::Json => serde_json::from_str(&contents) + .with_context(|| format!("Parsing json file {contents}"))?, + }; filedev .get_peripheral(pcopyname) .ok_or_else(|| { diff --git a/src/patch/mod.rs b/src/patch/mod.rs index be72a0b5..25e6663c 100644 --- a/src/patch/mod.rs +++ b/src/patch/mod.rs @@ -7,6 +7,7 @@ use std::borrow::Cow; use std::fs::File; use std::io::{Cursor, Read}; use std::path::{Path, PathBuf}; +use std::str::FromStr; use svd_parser::expand::{BlockPath, FieldPath, RegisterPath}; use svd_parser::svd::{ addressblock::AddressBlockBuilder, interrupt::InterruptBuilder, Access, AddressBlock, @@ -17,7 +18,7 @@ use svd_parser::svd::{ WriteConstraintRange, }; use svd_parser::SVDError::DimIndexParse; -use svd_rs::{BitRange, DimArrayIndex, DimElement, DimElementBuilder, MaybeArray}; +use svd_rs::{BitRange, Device, DimArrayIndex, DimElement, DimElementBuilder, MaybeArray}; use yaml_rust::{yaml::Hash, Yaml, YamlLoader}; use hashlink::linked_hash_map; @@ -35,6 +36,7 @@ mod register; mod yaml_ext; use yaml_ext::{AsType, GetVal, ToYaml}; +use crate::common::input_format::InputFormat; use crate::get_encoder_config; const VAL_LVL: ValidateLevel = ValidateLevel::Weak; @@ -115,8 +117,30 @@ pub fn process_file( let encoder_config = get_encoder_config(format_config)?; - let mut svd_out = process_reader(File::open(svdpath)?, &doc, &encoder_config, config)?; - std::io::copy(&mut svd_out, &mut File::create(svdpath_out)?)?; + let input_format = svdpath + .extension() + .map(|ext_os| ext_os.to_str().expect("_svd is str")) + .and_then(|ext| InputFormat::from_str(ext).ok()) + .unwrap_or(InputFormat::Xml); + + match input_format { + InputFormat::Xml => { + let mut svd_out = process_reader(File::open(svdpath)?, &doc, &encoder_config, config)?; + std::io::copy(&mut svd_out, &mut File::create(svdpath_out)?)?; + } + #[cfg(feature = "yaml")] + InputFormat::Yaml => { + let dev = serde_yaml::from_str(&std::fs::read_to_string(svdpath)?)?; + let mut svd_out = process_device(dev, &doc, &encoder_config, config)?; + std::io::copy(&mut svd_out, &mut File::create(svdpath_out)?)?; + } + #[cfg(feature = "json")] + InputFormat::Json => { + let dev = serde_json::from_str(&std::fs::read_to_string(svdpath)?)?; + let mut svd_out = process_device(dev, &doc, &encoder_config, config)?; + std::io::copy(&mut svd_out, &mut File::create(svdpath_out)?)?; + } + }; Ok(()) } @@ -131,8 +155,16 @@ pub fn process_reader( svd.read_to_string(&mut contents)?; let mut parser_config = svd_parser::Config::default(); parser_config.validate_level = ValidateLevel::Disabled; - let mut dev = svd_parser::parse_with_config(&contents, &parser_config)?; + let dev = svd_parser::parse_with_config(&contents, &parser_config)?; + process_device(dev, patch, format_config, config) +} +fn process_device( + mut dev: Device, + patch: &Yaml, + format_config: &EncoderConfig, + config: &Config, +) -> Result { // Process device dev.process(patch.hash()?, config).with_context(|| { let name = &dev.name;