Skip to content

Commit

Permalink
do not merge rules
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Dec 23, 2023
1 parent 3f9264e commit 0084574
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/patch/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl DeviceExt for Device {

// Now process all peripherals
for (periphspec, val) in device {
let periphspec = periphspec.str()?;
let periphspec = periphspec.key()?;
if !periphspec.starts_with('_') {
//val["_path"] = device["_path"]; // TODO: check
self.process_peripheral(periphspec, val.hash()?, config)
Expand Down
37 changes: 32 additions & 5 deletions src/patch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,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) => {
Expand All @@ -208,7 +208,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");
}
}
_ => {}
Expand All @@ -223,18 +223,45 @@ 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");
}
_ => {}
},
_ => {}
}
}
}
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());
}
Expand Down
8 changes: 4 additions & 4 deletions src/patch/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ impl PeripheralExt for Peripheral {

// Handle registers
for (rspec, register) in pmod {
let rspec = rspec.str()?;
let rspec = rspec.key()?;
if !rspec.starts_with('_') {
self.process_register(rspec, register.hash()?, config)
.with_context(|| format!("According to `{rspec}`"))?;
Expand All @@ -353,7 +353,7 @@ impl PeripheralExt for Peripheral {

// Handle clusters
for (cspec, cluster) in pmod.hash_iter("_clusters") {
let cspec = cspec.str()?;
let cspec = cspec.key()?;
if !cspec.starts_with('_') {
self.process_cluster(cspec, cluster.hash()?, config)
.with_context(|| format!("According to `{cspec}`"))?;
Expand Down Expand Up @@ -850,7 +850,7 @@ impl ClusterExt for Cluster {

// Handle clusters
for (cspec, cluster) in pmod.hash_iter("_clusters") {
let cspec = cspec.str()?;
let cspec = cspec.key()?;
if !cspec.starts_with('_') {
self.process_cluster(cspec, cluster.hash()?, config)
.with_context(|| format!("According to `{cspec}`"))?;
Expand All @@ -859,7 +859,7 @@ impl ClusterExt for Cluster {

// Handle registers
for (rspec, register) in pmod {
let rspec = rspec.str()?;
let rspec = rspec.key()?;
if !rspec.starts_with('_') {
self.process_register(rspec, register.hash()?, config)
.with_context(|| format!("According to `{rspec}`"))?;
Expand Down
2 changes: 1 addition & 1 deletion src/patch/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,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 !fspec.starts_with('_') {
self.process_field(pname, fspec, field, config)
.with_context(|| format!("Processing field matched to `{fspec}`"))?;
Expand Down
103 changes: 91 additions & 12 deletions src/patch/yaml_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:?}")]
Expand All @@ -23,6 +25,7 @@ pub trait AsType {
fn hash(&self) -> Result<&Hash, YamlError>;
fn vec(&self) -> Result<&Vec<Yaml>, YamlError>;
fn str(&self) -> Result<&str, YamlError>;
fn key(&self) -> Result<&str, YamlError>;
fn i64(&self) -> Result<i64, YamlError>;
fn bool(&self) -> Result<bool, YamlError>;
}
Expand All @@ -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<i64, YamlError> {
parse_i64(self).ok_or_else(|| YamlError::NotInt(self.clone()))
}
Expand Down Expand Up @@ -148,26 +164,29 @@ impl<'a> Iterator for OverStringIter<'a> {

type HashIter<'a> = OptIter<linked_hash_map::Iter<'a, Yaml, Yaml>>;

pub trait GetVal {
fn get_bool(&self, k: &str) -> Result<Option<bool>>;
fn get_i64(&self, k: &str) -> Result<Option<i64>>;
fn get_u64(&self, k: &str) -> Result<Option<u64>> {
pub trait GetVal<K>
where
K: ?Sized,
{
fn get_bool(&self, k: &K) -> Result<Option<bool>>;
fn get_i64(&self, k: &K) -> Result<Option<i64>>;
fn get_u64(&self, k: &K) -> Result<Option<u64>> {
self.get_i64(k).map(|v| v.map(|v| v as u64))
}
fn get_u32(&self, k: &str) -> Result<Option<u32>> {
fn get_u32(&self, k: &K) -> Result<Option<u32>> {
self.get_i64(k).map(|v| v.map(|v| v as u32))
}
fn get_str(&self, k: &str) -> Result<Option<&str>>;
fn get_string(&self, k: &str) -> Result<Option<String>> {
fn get_str(&self, k: &K) -> Result<Option<&str>>;
fn get_string(&self, k: &K) -> Result<Option<String>> {
self.get_str(k).map(|v| v.map(From::from))
}
fn get_hash(&self, k: &str) -> Result<Option<&Hash>>;
fn hash_iter<'a>(&'a self, k: &str) -> HashIter<'a>;
fn get_vec(&self, k: &str) -> Result<Option<&Vec<Yaml>>>;
fn str_vec_iter<'a>(&'a self, k: &str) -> Result<OptIter<OverStringIter<'a>>>;
fn get_hash(&self, k: &K) -> Result<Option<&Hash>>;
fn hash_iter<'a>(&'a self, k: &K) -> HashIter<'a>;
fn get_vec(&self, k: &K) -> Result<Option<&Vec<Yaml>>>;
fn str_vec_iter<'a>(&'a self, k: &K) -> Result<OptIter<OverStringIter<'a>>>;
}

impl GetVal for Hash {
impl GetVal<str> for Hash {
fn get_bool(&self, k: &str) -> Result<Option<bool>> {
match self.get(&k.to_yaml()) {
None => Ok(None),
Expand Down Expand Up @@ -230,3 +249,63 @@ impl GetVal for Hash {
}))
}
}

impl GetVal<Yaml> for Hash {
fn get_bool(&self, k: &Yaml) -> Result<Option<bool>> {
match self.get(k) {
None => Ok(None),
Some(v) => v
.bool()
.with_context(|| format!("Under key `{k:?}`"))
.map(Some),
}
}
fn get_i64(&self, k: &Yaml) -> Result<Option<i64>> {
match self.get(k) {
None => Ok(None),
Some(v) => v
.i64()
.with_context(|| format!("Under key `{k:?}`"))
.map(Some),
}
}
fn get_str(&self, k: &Yaml) -> Result<Option<&str>> {
match self.get(k) {
None => Ok(None),
Some(v) => v
.str()
.with_context(|| format!("Under key `{k:?}`"))
.map(Some),
}
}
fn get_hash(&self, k: &Yaml) -> Result<Option<&Hash>> {
match self.get(k) {
None => Ok(None),
Some(v) => v
.hash()
.with_context(|| format!("Under key `{k:?}`"))
.map(Some),
}
}
fn hash_iter<'a>(&'a self, k: &Yaml) -> HashIter<'a> {
HashIter::new(self.get(k).and_then(Yaml::as_hash).map(|h| h.iter()))
}
fn get_vec(&self, k: &Yaml) -> Result<Option<&Vec<Yaml>>> {
match self.get(k) {
None => Ok(None),
Some(v) => v
.vec()
.with_context(|| format!("Under key `{k:?}`"))
.map(Some),
}
}
fn str_vec_iter<'a>(&'a self, k: &Yaml) -> Result<OptIter<OverStringIter<'a>>> {
Ok(OptIter::new(match self.get(k) {
None => None,
Some(y) if matches!(y, Yaml::String(_) | Yaml::Array(_)) => {
Some(OverStringIter(y, None))
}
_ => return Err(anyhow!("`{k:?}` requires string value or array of strings")),
}))
}
}

0 comments on commit 0084574

Please sign in to comment.