From a99a3adc925afc0248dcf16cd8886fe1ac603aa3 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sat, 11 Nov 2023 14:57:07 +0300 Subject: [PATCH] do not merge rules --- src/patch/device.rs | 2 +- src/patch/mod.rs | 37 ++++++++++++++++++++++++++++++++----- src/patch/peripheral.rs | 8 ++++---- src/patch/register.rs | 2 +- src/patch/yaml_ext.rs | 16 ++++++++++++++++ 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/patch/device.rs b/src/patch/device.rs index e7a3cb1..9890b07 100644 --- a/src/patch/device.rs +++ b/src/patch/device.rs @@ -171,7 +171,7 @@ impl DeviceExt for Device { // Now process all peripherals for (periphspec, val) in device { - let periphspec = periphspec.str()?; + let periphspec = periphspec.key()?; if !Self::KEYWORDS.contains(&periphspec) { //val["_path"] = device["_path"]; // TODO: check self.process_peripheral(periphspec, val.hash()?, config) diff --git a/src/patch/mod.rs b/src/patch/mod.rs index f7e5fe4..5027420 100644 --- a/src/patch/mod.rs +++ b/src/patch/mod.rs @@ -221,11 +221,11 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> { for (key, val) in child.iter() { match key { Yaml::String(key) if key == "_path" || key == "_include" => continue, - key if parent.contains_key(key) => { + Yaml::String(k) if parent.contains_key(key) && k.starts_with('_') => { if let Entry::Occupied(mut e) = parent.entry(key.clone()) { match e.get_mut() { el if el == val => { - println!("In {key:?}: dublicate rule {val:?}, ignored"); + println!("In {k}: dublicate rule {val:?}, ignored"); } Yaml::Array(a) => match val { Yaml::Array(val) => { @@ -235,7 +235,7 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> { if !a.contains(val) { a.push(val.clone()); } else { - println!("In {key:?}: dublicate rule {val:?}, ignored"); + println!("In {k}: dublicate rule {val:?}, ignored"); } } _ => {} @@ -250,11 +250,11 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> { a.insert(0, s.clone()); e.insert(Yaml::Array(a)); } else { - println!("In {key:?}: dublicate rule {s:?}, ignored"); + println!("In {k}: dublicate rule {s:?}, ignored"); } } s2 if matches!(s2, Yaml::String(_)) => { - println!("In {key:?}: conflicting rules {s:?} and {s2:?}, ignored"); + println!("In {k}: conflicting rules {s:?} and {s2:?}, ignored"); } _ => {} }, @@ -262,6 +262,33 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> { } } } + Yaml::String(_) if parent.contains_key(key) => { + let mut i = 0; + loop { + let key = Yaml::Array(vec![key.clone(), Yaml::Integer(i)]); + if !parent.contains_key(&key) { + parent.insert(key, val.clone()); + break; + } + i += 1; + } + } + Yaml::Array(a) + if parent.contains_key(key) + && matches!(a.as_slice(), [Yaml::String(_), Yaml::Integer(_)]) => + { + if let [k @ Yaml::String(_), Yaml::Integer(_)] = a.as_slice() { + let mut i = 0; + loop { + let key = Yaml::Array(vec![k.clone(), Yaml::Integer(i)]); + if !parent.contains_key(&key) { + parent.insert(key, val.clone()); + break; + } + i += 1; + } + } + } _ => { parent.insert(key.clone(), val.clone()); } diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index cd690b3..4f1b4f4 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -1251,7 +1251,7 @@ impl PeripheralExt for Peripheral { // Handle registers or clusters for (rcspec, rcmod) in pmod { - let rcspec = rcspec.str()?; + let rcspec = rcspec.key()?; if Self::KEYWORDS.contains(&rcspec) { continue; } @@ -1281,7 +1281,7 @@ impl PeripheralExt for Peripheral { // Handle clusters for (cspec, cluster) in pmod.hash_iter("_clusters") { - let cspec = cspec.str()?; + let cspec = cspec.key()?; self.process_cluster(cspec, cluster.hash()?, &ppath, config) .with_context(|| format!("According to `{cspec}`"))?; } @@ -1561,14 +1561,14 @@ impl ClusterExt for Cluster { // Handle clusters for (cspec, cluster) in cmod.hash_iter("_clusters") { - let cspec = cspec.str()?; + let cspec = cspec.key()?; self.process_cluster(cspec, cluster.hash()?, &cpath, config) .with_context(|| format!("According to `{cspec}`"))?; } // Handle registers or clusters for (rcspec, rcmod) in cmod { - let rcspec = rcspec.str()?; + let rcspec = rcspec.key()?; if Self::KEYWORDS.contains(&rcspec) { continue; } diff --git a/src/patch/register.rs b/src/patch/register.rs index 170aa86..8d580dc 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -263,7 +263,7 @@ impl RegisterExt for Register { // Handle fields if config.update_fields { for (fspec, field) in rmod { - let fspec = fspec.str()?; + let fspec = fspec.key()?; if Self::KEYWORDS.contains(&fspec) { continue; } diff --git a/src/patch/yaml_ext.rs b/src/patch/yaml_ext.rs index d435b61..f2b3b00 100644 --- a/src/patch/yaml_ext.rs +++ b/src/patch/yaml_ext.rs @@ -12,6 +12,8 @@ pub enum YamlError { NotVec(Yaml), #[error("Value is not a string: {0:?}")] NotStr(Yaml), + #[error("Value is not a supported hash key: {0:?}")] + NotKey(Yaml), #[error("Value is not integer: {0:?}")] NotInt(Yaml), #[error("Value is not boolean: {0:?}")] @@ -23,6 +25,7 @@ pub trait AsType { fn hash(&self) -> Result<&Hash, YamlError>; fn vec(&self) -> Result<&Vec, YamlError>; fn str(&self) -> Result<&str, YamlError>; + fn key(&self) -> Result<&str, YamlError>; fn i64(&self) -> Result; fn bool(&self) -> Result; } @@ -44,6 +47,19 @@ impl AsType for Yaml { fn str(&self) -> Result<&str, YamlError> { self.as_str().ok_or_else(|| YamlError::NotStr(self.clone())) } + fn key(&self) -> Result<&str, YamlError> { + match self { + Yaml::String(k) => Ok(k), + Yaml::Array(a) if matches!(a.as_slice(), [Yaml::String(_), Yaml::Integer(_)]) => { + if let [Yaml::String(k), Yaml::Integer(_)] = a.as_slice() { + Ok(k) + } else { + unreachable!() + } + } + _ => Err(YamlError::NotKey(self.clone())), + } + } fn i64(&self) -> Result { parse_i64(self).ok_or_else(|| YamlError::NotInt(self.clone())) }