diff --git a/.gitignore b/.gitignore index 26a0769..08c1263 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ [._]*.sw[a-p] *.org *.rs.bk -target \ No newline at end of file +target +.DS_Store diff --git a/src/transform/map_enum_variants.rs b/src/transform/map_enum_variants.rs new file mode 100644 index 0000000..5813b08 --- /dev/null +++ b/src/transform/map_enum_variants.rs @@ -0,0 +1,38 @@ +//! Simple transform for enum variant names +//! +//! This is useful when an SVD contains enum variants with purely numeric identifiers. +//! It is not meant to be used to apply inflection, that's what the `Sanitize` transform is for. + +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; + +use super::common::*; +use crate::ir::*; + +#[derive(Debug, Serialize, Deserialize)] +pub struct MapEnumVariants { + #[serde(rename = "enum")] + pub enumm: RegexSet, + #[serde(default)] + pub variants: BTreeMap, + #[serde(default)] + pub descriptions: BTreeMap, +} + +impl MapEnumVariants { + pub fn run(&self, ir: &mut IR) -> anyhow::Result<()> { + for id in match_all(ir.enums.keys().cloned(), &self.enumm) { + let e = ir.enums.get_mut(&id).unwrap(); + for variant in e.variants.iter_mut() { + if let Some(new_description) = self.descriptions.get(&variant.name) { + variant.description = Some(new_description.clone()); + } + if let Some(new_name) = self.variants.get(&variant.name) { + variant.name = new_name.clone(); + } + } + } + Ok(()) + } +} diff --git a/src/transform/mod.rs b/src/transform/mod.rs index cb3e33b..50481b7 100644 --- a/src/transform/mod.rs +++ b/src/transform/mod.rs @@ -271,4 +271,5 @@ transforms!( rename_interrupts::RenameInterrupts, rename_peripherals::RenamePeripherals, clean_descriptions::CleanDescriptions, + map_enum_variants::MapEnumVariants, ); diff --git a/tests/map_enum_variants.rs b/tests/map_enum_variants.rs new file mode 100644 index 0000000..e32783d --- /dev/null +++ b/tests/map_enum_variants.rs @@ -0,0 +1,51 @@ +use chiptool::{ir::IR, transform::map_enum_variants::MapEnumVariants}; + +#[test] +fn duplicate_ir_enums_should_be_updated() -> Result<(), Box> { + let input_yaml = r#" + block/BLOCK: + items: + - name: register + byte_offset: 0 + bit_size: 32 + fieldset: regs::Fieldset + fieldset/regs::Fieldset: + fields: + - name: reserved + bit_offset: 0 + bit_size: 3 + enum: vals::Enumm + enum/vals::Enumm: + bit_size: 3 + variants: + - { name: VariantOne, value: 0b001 } + - { name: VariantTwo, value: 0b010 } + - { name: VariantThree, value: 0b011 } + "#; + + let transform_yaml = r#" + !MapEnumVariants + enum: vals::Enumm + variants: + VariantOne: _1 + VariantTwo: _2 + VariantThree: _3 + "#; + + let mut ir: IR = serde_yaml::from_slice(input_yaml.as_bytes())?; + + let transform = serde_yaml::from_slice::(transform_yaml.as_bytes())?; + transform.run(&mut ir)?; + + let enumm = ir.enums.get("vals::Enumm").expect("Enum not found"); + + let variant_names = enumm + .variants + .iter() + .map(|field| &field.name) + .collect::>(); + + assert_eq!(variant_names, &["_1", "_2", "_3"]); + + Ok(()) +}