Skip to content

Commit c7b218f

Browse files
committed
do not merge rules
1 parent 79959a7 commit c7b218f

File tree

5 files changed

+131
-24
lines changed

5 files changed

+131
-24
lines changed

src/patch/device.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl DeviceExt for Device {
151151

152152
// Now process all peripherals
153153
for (periphspec, val) in device {
154-
let periphspec = periphspec.str()?;
154+
let periphspec = periphspec.key()?;
155155
if !periphspec.starts_with('_') {
156156
//val["_path"] = device["_path"]; // TODO: check
157157
self.process_peripheral(periphspec, val.hash()?, update_fields)

src/patch/mod.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ fn abspath(frompath: &Path, relpath: &Path) -> Result<PathBuf, std::io::Error> {
9797
/// Recursively loads any included YAML files.
9898
pub fn yaml_includes(parent: &mut Hash) -> Result<Vec<PathBuf>> {
9999
let y_path = "_path".to_yaml();
100+
let _include = "_include".to_yaml();
100101
let mut included = vec![];
101102
let self_path = PathBuf::from(parent.get(&y_path).unwrap().str()?);
102103
let inc = parent.get_vec("_include")?.unwrap_or(&Vec::new()).clone();
@@ -123,7 +124,7 @@ pub fn yaml_includes(parent: &mut Hash) -> Result<Vec<PathBuf>> {
123124
for (pspec, val) in child.iter_mut() {
124125
if !pspec.str()?.starts_with('_') {
125126
match val {
126-
Yaml::Hash(val) if val.contains_key(&"_include".to_yaml()) => {
127+
Yaml::Hash(val) if val.contains_key(&_include) => {
127128
val.insert(y_path.clone(), ypath.clone());
128129
included.extend(yaml_includes(val)?);
129130
}
@@ -145,11 +146,11 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> {
145146
for (key, val) in child.iter() {
146147
match key {
147148
Yaml::String(key) if key == "_path" || key == "_include" => continue,
148-
key if parent.contains_key(key) => {
149+
Yaml::String(k) if parent.contains_key(key) && k.starts_with("_") => {
149150
if let Entry::Occupied(mut e) = parent.entry(key.clone()) {
150151
match e.get_mut() {
151152
el if el == val => {
152-
println!("In {key:?}: dublicate rule {val:?}, ignored");
153+
println!("In {k}: dublicate rule {val:?}, ignored");
153154
}
154155
Yaml::Array(a) => match val {
155156
Yaml::Array(val) => {
@@ -159,7 +160,7 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> {
159160
if !a.contains(val) {
160161
a.push(val.clone());
161162
} else {
162-
println!("In {key:?}: dublicate rule {val:?}, ignored");
163+
println!("In {k}: dublicate rule {val:?}, ignored");
163164
}
164165
}
165166
_ => {}
@@ -174,18 +175,45 @@ fn update_dict(parent: &mut Hash, child: &Hash) -> Result<()> {
174175
a.insert(0, s.clone());
175176
e.insert(Yaml::Array(a));
176177
} else {
177-
println!("In {key:?}: dublicate rule {s:?}, ignored");
178+
println!("In {k}: dublicate rule {s:?}, ignored");
178179
}
179180
}
180181
s2 if matches!(s2, Yaml::String(_)) => {
181-
println!("In {key:?}: conflicting rules {s:?} and {s2:?}, ignored");
182+
println!("In {k}: conflicting rules {s:?} and {s2:?}, ignored");
182183
}
183184
_ => {}
184185
},
185186
_ => {}
186187
}
187188
}
188189
}
190+
Yaml::String(_) if parent.contains_key(key) => {
191+
let mut i = 0;
192+
loop {
193+
let key = Yaml::Array(vec![key.clone(), Yaml::Integer(i)]);
194+
if !parent.contains_key(&key) {
195+
parent.insert(key, val.clone());
196+
break;
197+
}
198+
i += 1;
199+
}
200+
}
201+
Yaml::Array(a)
202+
if parent.contains_key(key)
203+
&& matches!(a.as_slice(), [Yaml::String(_), Yaml::Integer(_)]) =>
204+
{
205+
if let [k @ Yaml::String(_), Yaml::Integer(_)] = a.as_slice() {
206+
let mut i = 0;
207+
loop {
208+
let key = Yaml::Array(vec![k.clone(), Yaml::Integer(i)]);
209+
if !parent.contains_key(&key) {
210+
parent.insert(key, val.clone());
211+
break;
212+
}
213+
i += 1;
214+
}
215+
}
216+
}
189217
_ => {
190218
parent.insert(key.clone(), val.clone());
191219
}

src/patch/peripheral.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ impl PeripheralExt for Peripheral {
335335

336336
// Handle registers
337337
for (rspec, register) in pmod {
338-
let rspec = rspec.str()?;
338+
let rspec = rspec.key()?;
339339
if !rspec.starts_with('_') {
340340
self.process_register(rspec, register.hash()?, update_fields)
341341
.with_context(|| format!("According to `{rspec}`"))?;
@@ -358,7 +358,7 @@ impl PeripheralExt for Peripheral {
358358

359359
// Handle clusters
360360
for (cspec, cluster) in pmod.hash_iter("_clusters") {
361-
let cspec = cspec.str()?;
361+
let cspec = cspec.key()?;
362362
if !cspec.starts_with('_') {
363363
self.process_cluster(cspec, cluster.hash()?, update_fields)
364364
.with_context(|| format!("According to `{cspec}`"))?;
@@ -840,7 +840,7 @@ impl ClusterExt for Cluster {
840840

841841
// Handle clusters
842842
for (cspec, cluster) in pmod.hash_iter("_clusters") {
843-
let cspec = cspec.str()?;
843+
let cspec = cspec.key()?;
844844
if !cspec.starts_with('_') {
845845
self.process_cluster(cspec, cluster.hash()?, update_fields)
846846
.with_context(|| format!("According to `{cspec}`"))?;
@@ -849,7 +849,7 @@ impl ClusterExt for Cluster {
849849

850850
// Handle registers
851851
for (rspec, register) in pmod {
852-
let rspec = rspec.str()?;
852+
let rspec = rspec.key()?;
853853
if !rspec.starts_with('_') {
854854
self.process_register(rspec, register.hash()?, update_fields)
855855
.with_context(|| format!("According to `{rspec}`"))?;

src/patch/register.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl RegisterExt for Register {
172172
// Handle fields
173173
if update_fields {
174174
for (fspec, field) in rmod {
175-
let fspec = fspec.str()?;
175+
let fspec = fspec.key()?;
176176
if !fspec.starts_with('_') {
177177
self.process_field(pname, fspec, field)
178178
.with_context(|| format!("Processing field matched to `{fspec}`"))?;

src/patch/yaml_ext.rs

+91-12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ pub enum YamlError {
1212
NotVec(Yaml),
1313
#[error("Value is not a string: {0:?}")]
1414
NotStr(Yaml),
15+
#[error("Value is not a supported hash key: {0:?}")]
16+
NotKey(Yaml),
1517
#[error("Value is not integer: {0:?}")]
1618
NotInt(Yaml),
1719
#[error("Value is not boolean: {0:?}")]
@@ -23,6 +25,7 @@ pub trait AsType {
2325
fn hash(&self) -> Result<&Hash, YamlError>;
2426
fn vec(&self) -> Result<&Vec<Yaml>, YamlError>;
2527
fn str(&self) -> Result<&str, YamlError>;
28+
fn key(&self) -> Result<&str, YamlError>;
2629
fn i64(&self) -> Result<i64, YamlError>;
2730
fn bool(&self) -> Result<bool, YamlError>;
2831
}
@@ -44,6 +47,19 @@ impl AsType for Yaml {
4447
fn str(&self) -> Result<&str, YamlError> {
4548
self.as_str().ok_or_else(|| YamlError::NotStr(self.clone()))
4649
}
50+
fn key(&self) -> Result<&str, YamlError> {
51+
match self {
52+
Yaml::String(k) => Ok(k),
53+
Yaml::Array(a) if matches!(a.as_slice(), [Yaml::String(_), Yaml::Integer(_)]) => {
54+
if let [Yaml::String(k), Yaml::Integer(_)] = a.as_slice() {
55+
Ok(k)
56+
} else {
57+
unreachable!()
58+
}
59+
}
60+
_ => Err(YamlError::NotKey(self.clone())),
61+
}
62+
}
4763
fn i64(&self) -> Result<i64, YamlError> {
4864
parse_i64(self).ok_or_else(|| YamlError::NotInt(self.clone()))
4965
}
@@ -148,26 +164,29 @@ impl<'a> Iterator for OverStringIter<'a> {
148164

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

151-
pub trait GetVal {
152-
fn get_bool(&self, k: &str) -> Result<Option<bool>>;
153-
fn get_i64(&self, k: &str) -> Result<Option<i64>>;
154-
fn get_u64(&self, k: &str) -> Result<Option<u64>> {
167+
pub trait GetVal<K>
168+
where
169+
K: ?Sized,
170+
{
171+
fn get_bool(&self, k: &K) -> Result<Option<bool>>;
172+
fn get_i64(&self, k: &K) -> Result<Option<i64>>;
173+
fn get_u64(&self, k: &K) -> Result<Option<u64>> {
155174
self.get_i64(k).map(|v| v.map(|v| v as u64))
156175
}
157-
fn get_u32(&self, k: &str) -> Result<Option<u32>> {
176+
fn get_u32(&self, k: &K) -> Result<Option<u32>> {
158177
self.get_i64(k).map(|v| v.map(|v| v as u32))
159178
}
160-
fn get_str(&self, k: &str) -> Result<Option<&str>>;
161-
fn get_string(&self, k: &str) -> Result<Option<String>> {
179+
fn get_str(&self, k: &K) -> Result<Option<&str>>;
180+
fn get_string(&self, k: &K) -> Result<Option<String>> {
162181
self.get_str(k).map(|v| v.map(From::from))
163182
}
164-
fn get_hash(&self, k: &str) -> Result<Option<&Hash>>;
165-
fn hash_iter<'a>(&'a self, k: &str) -> HashIter<'a>;
166-
fn get_vec(&self, k: &str) -> Result<Option<&Vec<Yaml>>>;
167-
fn str_vec_iter<'a>(&'a self, k: &str) -> Result<OptIter<OverStringIter<'a>>>;
183+
fn get_hash(&self, k: &K) -> Result<Option<&Hash>>;
184+
fn hash_iter<'a>(&'a self, k: &K) -> HashIter<'a>;
185+
fn get_vec(&self, k: &K) -> Result<Option<&Vec<Yaml>>>;
186+
fn str_vec_iter<'a>(&'a self, k: &K) -> Result<OptIter<OverStringIter<'a>>>;
168187
}
169188

170-
impl GetVal for Hash {
189+
impl GetVal<str> for Hash {
171190
fn get_bool(&self, k: &str) -> Result<Option<bool>> {
172191
match self.get(&k.to_yaml()) {
173192
None => Ok(None),
@@ -230,3 +249,63 @@ impl GetVal for Hash {
230249
}))
231250
}
232251
}
252+
253+
impl GetVal<Yaml> for Hash {
254+
fn get_bool(&self, k: &Yaml) -> Result<Option<bool>> {
255+
match self.get(&k) {
256+
None => Ok(None),
257+
Some(v) => v
258+
.bool()
259+
.with_context(|| format!("Under key `{k:?}`"))
260+
.map(Some),
261+
}
262+
}
263+
fn get_i64(&self, k: &Yaml) -> Result<Option<i64>> {
264+
match self.get(&k) {
265+
None => Ok(None),
266+
Some(v) => v
267+
.i64()
268+
.with_context(|| format!("Under key `{k:?}`"))
269+
.map(Some),
270+
}
271+
}
272+
fn get_str(&self, k: &Yaml) -> Result<Option<&str>> {
273+
match self.get(&k) {
274+
None => Ok(None),
275+
Some(v) => v
276+
.str()
277+
.with_context(|| format!("Under key `{k:?}`"))
278+
.map(Some),
279+
}
280+
}
281+
fn get_hash(&self, k: &Yaml) -> Result<Option<&Hash>> {
282+
match self.get(&k) {
283+
None => Ok(None),
284+
Some(v) => v
285+
.hash()
286+
.with_context(|| format!("Under key `{k:?}`"))
287+
.map(Some),
288+
}
289+
}
290+
fn hash_iter<'a>(&'a self, k: &Yaml) -> HashIter<'a> {
291+
HashIter::new(self.get(&k).and_then(Yaml::as_hash).map(|h| h.iter()))
292+
}
293+
fn get_vec(&self, k: &Yaml) -> Result<Option<&Vec<Yaml>>> {
294+
match self.get(&k) {
295+
None => Ok(None),
296+
Some(v) => v
297+
.vec()
298+
.with_context(|| format!("Under key `{k:?}`"))
299+
.map(Some),
300+
}
301+
}
302+
fn str_vec_iter<'a>(&'a self, k: &Yaml) -> Result<OptIter<OverStringIter<'a>>> {
303+
Ok(OptIter::new(match self.get(&k) {
304+
None => None,
305+
Some(y) if matches!(y, Yaml::String(_) | Yaml::Array(_)) => {
306+
Some(OverStringIter(y, None))
307+
}
308+
_ => return Err(anyhow!("`{k:?}` requires string value or array of strings")),
309+
}))
310+
}
311+
}

0 commit comments

Comments
 (0)