Skip to content

Commit 848fe7a

Browse files
authored
Merge pull request #172 from rust-embedded/sort-derived-fields
Move field with derived enums before other, use Itertools::join
2 parents 9fbd8a0 + 7cbe747 commit 848fe7a

File tree

5 files changed

+96
-87
lines changed

5 files changed

+96
-87
lines changed

CHANGELOG-rust.md

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This changelog tracks the Rust `svdtools` project. See
55

66
## [Unreleased]
77

8+
* Move field with derived enums before other
9+
810
## [v0.3.4] 2023-10-14
911

1012
* Revert #145

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ liquid = "0.26.0"
4747
once_cell = "1.18.0"
4848
rayon = "1.7.0"
4949
regex = "1.9.1"
50+
itertools = "0.11.0"
5051

5152
[dev-dependencies]
5253
tempfile = "3.3"

src/patch/device.rs

+60-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::{anyhow, Context};
2+
use itertools::Itertools;
23
use svd_parser::svd::{Device, Peripheral, PeripheralInfo};
34
use yaml_rust::{yaml::Hash, Yaml};
45

@@ -305,32 +306,60 @@ impl DeviceExt for Device {
305306
return Err(anyhow!("derive: incorrect syntax for {pname}"));
306307
};
307308

308-
if !pderive.contains('.') {
309-
self.get_peripheral(pderive)
310-
.ok_or_else(|| anyhow!("peripheral {pderive} not found"))?;
311-
}
309+
let derived_pos = if !pderive.contains('.') {
310+
let Some((i, _)) = self
311+
.peripherals
312+
.iter()
313+
.enumerate()
314+
.find(|(_, f)| f.name == pderive)
315+
else {
316+
return Err(anyhow!("peripheral {pderive} not found"));
317+
};
318+
Some(i)
319+
} else {
320+
None
321+
};
312322

313-
match self.get_mut_peripheral(pname) {
314-
Some(peripheral) => peripheral.modify_from(info, VAL_LVL)?,
323+
let mut min_pos = self.peripherals.len();
324+
match self
325+
.peripherals
326+
.iter_mut()
327+
.enumerate()
328+
.find(|(_, f)| f.name == pname)
329+
{
330+
Some((i, peripheral)) => {
331+
min_pos = i;
332+
peripheral.modify_from(info, VAL_LVL)?;
333+
}
315334
None => {
316335
let peripheral = info.name(pname.into()).build(VAL_LVL)?.single();
317336
self.peripherals.push(peripheral);
318337
}
319338
}
320339

321-
for p in self
322-
.peripherals
323-
.iter_mut()
324-
.filter(|p| p.derived_from.as_deref() == Some(pname))
325-
{
326-
p.derived_from = Some(pderive.into());
340+
for (i, p) in self.peripherals.iter_mut().enumerate() {
341+
if p.derived_from.as_deref() == Some(pname) {
342+
if i < min_pos {
343+
min_pos = i;
344+
}
345+
p.derived_from = Some(pderive.into());
346+
}
347+
}
348+
if let Some(derived_pos) = derived_pos {
349+
if derived_pos > min_pos {
350+
let p = self.peripherals.remove(derived_pos);
351+
self.peripherals.insert(min_pos, p);
352+
}
327353
}
328354
Ok(())
329355
}
330356

331357
fn rebase_peripheral(&mut self, pnew: &str, pold: &str) -> PatchResult {
332-
let old = self
333-
.get_mut_peripheral(pold)
358+
let (mut min_pos, old) = self
359+
.peripherals
360+
.iter_mut()
361+
.enumerate()
362+
.find(|(_, f)| f.name == pold)
334363
.ok_or_else(|| anyhow!("peripheral {pold} not found"))?;
335364
let mut d = std::mem::replace(
336365
old,
@@ -346,19 +375,27 @@ impl DeviceExt for Device {
346375
.build(VAL_LVL)?
347376
.single(),
348377
);
349-
let new = self
350-
.get_mut_peripheral(pnew)
378+
let (new_pos, new) = self
379+
.peripherals
380+
.iter_mut()
381+
.enumerate()
382+
.find(|(_, f)| f.name == pnew)
351383
.ok_or_else(|| anyhow!("peripheral {pnew} not found"))?;
352384
d.name = new.name.clone();
353385
d.base_address = new.base_address;
354386
d.interrupt = new.interrupt.clone();
355387
*new = d;
356-
for p in self
357-
.peripherals
358-
.iter_mut()
359-
.filter(|p| p.derived_from.as_deref() == Some(pold))
360-
{
361-
p.derived_from = Some(pnew.into());
388+
for (i, p) in self.peripherals.iter_mut().enumerate() {
389+
if p.derived_from.as_deref() == Some(pold) {
390+
if i < min_pos {
391+
min_pos = i;
392+
}
393+
p.derived_from = Some(pnew.into());
394+
}
395+
}
396+
if new_pos > min_pos {
397+
let p = self.peripherals.remove(new_pos);
398+
self.peripherals.insert(min_pos, p);
362399
}
363400
Ok(())
364401
}
@@ -389,11 +426,7 @@ impl DeviceExt for Device {
389426
if pcount == 0 {
390427
Err(anyhow!(
391428
"Could not find `{pspec}. Present peripherals: {}.`",
392-
self.peripherals
393-
.iter()
394-
.map(|p| p.name.as_str())
395-
.collect::<Vec<_>>()
396-
.join(", ")
429+
self.peripherals.iter().map(|p| p.name.as_str()).join(", ")
397430
))
398431
} else {
399432
Ok(())

src/patch/peripheral.rs

+10-31
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::{anyhow, Context};
2+
use itertools::Itertools;
23
use svd_parser::svd::{
34
self, Cluster, ClusterInfo, DimElement, Interrupt, Peripheral, Register, RegisterCluster,
45
RegisterInfo,
@@ -487,10 +488,7 @@ impl RegisterBlockExt for Peripheral {
487488
self.get_register(rderive).ok_or_else(|| {
488489
anyhow!(
489490
"register {rderive} not found. Present registers: {}.`",
490-
self.registers()
491-
.map(|r| r.name.as_str())
492-
.collect::<Vec<_>>()
493-
.join(", ")
491+
self.registers().map(|r| r.name.as_str()).join(", ")
494492
)
495493
})?;
496494

@@ -535,10 +533,8 @@ impl RegisterBlockExt for Peripheral {
535533
source.address_offset = ptag.address_offset;
536534
*ptag = source;
537535
} else {
538-
self.registers
539-
.as_mut()
540-
.unwrap()
541-
.push(RegisterCluster::Register(source))
536+
let registers = self.registers.get_or_insert_with(Vec::new);
537+
registers.push(RegisterCluster::Register(source));
542538
}
543539
Ok(())
544540
}
@@ -652,10 +648,7 @@ impl RegisterBlockExt for Peripheral {
652648
if rcount == 0 {
653649
Err(anyhow!(
654650
"Could not find `{pname}:{rspec}. Present registers: {}.`",
655-
self.registers()
656-
.map(|r| r.name.as_str())
657-
.collect::<Vec<_>>()
658-
.join(", ")
651+
self.registers().map(|r| r.name.as_str()).join(", ")
659652
))
660653
} else {
661654
Ok(())
@@ -674,10 +667,7 @@ impl RegisterBlockExt for Peripheral {
674667
if ccount == 0 {
675668
Err(anyhow!(
676669
"Could not find `{pname}:{cspec}. Present clusters: {}.`",
677-
self.clusters()
678-
.map(|c| c.name.as_str())
679-
.collect::<Vec<_>>()
680-
.join(", ")
670+
self.clusters().map(|c| c.name.as_str()).join(", ")
681671
))
682672
} else {
683673
Ok(())
@@ -966,10 +956,7 @@ impl RegisterBlockExt for Cluster {
966956
self.get_register(rderive).ok_or_else(|| {
967957
anyhow!(
968958
"register {rderive} not found. Present registers: {}.`",
969-
self.registers()
970-
.map(|r| r.name.as_str())
971-
.collect::<Vec<_>>()
972-
.join(", ")
959+
self.registers().map(|r| r.name.as_str()).join(", ")
973960
)
974961
})?;
975962

@@ -1117,10 +1104,7 @@ impl RegisterBlockExt for Cluster {
11171104
Err(anyhow!(
11181105
"Could not find `{pname}:{}:{rspec}. Present registers: {}.`",
11191106
self.name,
1120-
self.registers()
1121-
.map(|r| r.name.as_str())
1122-
.collect::<Vec<_>>()
1123-
.join(", ")
1107+
self.registers().map(|r| r.name.as_str()).join(", ")
11241108
))
11251109
} else {
11261110
Ok(())
@@ -1140,10 +1124,7 @@ impl RegisterBlockExt for Cluster {
11401124
Err(anyhow!(
11411125
"Could not find `{pname}:{}:{cspec}. Present clusters: {}.`",
11421126
self.name,
1143-
self.clusters()
1144-
.map(|c| c.name.as_str())
1145-
.collect::<Vec<_>>()
1146-
.join(", ")
1127+
self.clusters().map(|c| c.name.as_str()).join(", ")
11471128
))
11481129
} else {
11491130
Ok(())
@@ -1179,7 +1160,6 @@ fn collect_in_array(
11791160
RegisterCluster::Register(r) => Some(r.name.as_str()),
11801161
_ => None,
11811162
})
1182-
.collect::<Vec<_>>()
11831163
.join(", ")
11841164
));
11851165
}
@@ -1298,7 +1278,6 @@ fn collect_in_cluster(
12981278
RegisterCluster::Register(r) => Some(r.name.as_str()),
12991279
_ => None,
13001280
})
1301-
.collect::<Vec<_>>()
13021281
.join(", ")
13031282
));
13041283
}
@@ -1347,7 +1326,7 @@ fn collect_in_cluster(
13471326
if dim > 1 {
13481327
dim_increment = offsets[1] - offsets[0];
13491328
}
1350-
first = Some(rspec.clone());
1329+
first = Some(rspec);
13511330
}
13521331
if !check_offsets(&offsets, dim_increment) {
13531332
return Err(anyhow!(

src/patch/register.rs

+23-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::{anyhow, Context};
2+
use itertools::Itertools;
23
use svd_parser::svd::{
34
Access, BitRange, DimElement, EnumeratedValues, Field, FieldInfo, ModifiedWriteValues,
45
ReadAction, Register, RegisterInfo, Usage, WriteConstraint, WriteConstraintRange,
@@ -323,10 +324,7 @@ impl RegisterExt for Register {
323324
return Err(anyhow!(
324325
"Could not find any fields to merge {}:{key}. Present fields: {}.`",
325326
self.name,
326-
self.fields()
327-
.map(|f| f.name.as_str())
328-
.collect::<Vec<_>>()
329-
.join(", ")
327+
self.fields().map(|f| f.name.as_str()).join(", ")
330328
));
331329
}
332330
let mut bitwidth = 0;
@@ -377,10 +375,7 @@ impl RegisterExt for Register {
377375
return Err(anyhow!(
378376
"{}: fields {fspec} not found. Present fields: {}.`",
379377
self.name,
380-
self.fields()
381-
.map(|f| f.name.as_str())
382-
.collect::<Vec<_>>()
383-
.join(", ")
378+
self.fields().map(|f| f.name.as_str()).join(", ")
384379
));
385380
}
386381
fields.sort_by_key(|f| f.bit_range.offset);
@@ -443,10 +438,7 @@ impl RegisterExt for Register {
443438
return Err(anyhow!(
444439
"Could not find any fields to split {}:{fspec}. Present fields: {}.`",
445440
self.name,
446-
self.fields()
447-
.map(|f| f.name.as_str())
448-
.collect::<Vec<_>>()
449-
.join(", ")
441+
self.fields().map(|f| f.name.as_str()).join(", ")
450442
));
451443
}
452444
(Some(_), Some(_)) => {
@@ -664,10 +656,7 @@ impl RegisterExt for Register {
664656
// This is a derived enumeratedValues => Try to find the
665657
// original definition to extract its <usage>
666658
let mut derived_enums = self
667-
.fields
668-
.as_ref()
669-
.unwrap()
670-
.iter()
659+
.fields()
671660
.flat_map(|f| f.enumerated_values.iter())
672661
.filter(|e| e.name.as_deref() == Some(d));
673662
let orig_usage = match (derived_enums.next(), derived_enums.next()) {
@@ -697,21 +686,22 @@ impl RegisterExt for Register {
697686
set_enum(ftag, evs.clone(), orig_usage, true, access)?;
698687
}
699688
} else {
700-
let offsets = self
701-
.iter_fields(fspec)
702-
.map(|f| (f.bit_range.offset, f.name.to_string()))
703-
.collect::<Vec<_>>();
689+
let mut offsets: Vec<_> = Vec::new();
690+
for (i, f) in self.fields().enumerate() {
691+
if matchname(&f.name, fspec) {
692+
offsets.push((f.bit_range.offset, f.name.to_string(), i));
693+
}
694+
}
704695
if offsets.is_empty() {
705696
return Err(anyhow!(
706697
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
707698
self.name,
708-
self.fields()
709-
.map(|f| f.name.as_str())
710-
.collect::<Vec<_>>()
711-
.join(", ")
699+
self.fields().map(|f| f.name.as_str()).join(", ")
712700
));
713701
}
714-
let (min_offset, fname) = offsets.iter().min_by_key(|on| on.0).unwrap();
702+
let (min_offset, fname, min_offset_pos) =
703+
offsets.iter().min_by_key(|&on| on.0).unwrap();
704+
let min_pos = offsets.iter().map(|on| on.2).min().unwrap();
715705
let name = make_ev_name(&fname.replace("%s", ""), usage)?;
716706
for ftag in self.iter_fields(fspec) {
717707
let access = ftag.access.or(reg_access).unwrap_or_default();
@@ -735,6 +725,13 @@ impl RegisterExt for Register {
735725
)?;
736726
}
737727
}
728+
// Move field with derived enums before other
729+
if let Some(fields) = self.fields.as_mut() {
730+
if *min_offset_pos != min_pos {
731+
let f = fields.remove(*min_offset_pos);
732+
fields.insert(min_pos, f);
733+
}
734+
}
738735
}
739736
Ok(())
740737
}
@@ -752,10 +749,7 @@ impl RegisterExt for Register {
752749
return Err(anyhow!(
753750
"Could not find field {pname}:{}:{fspec}. Present fields: {}.`",
754751
self.name,
755-
self.fields()
756-
.map(|f| f.name.as_str())
757-
.collect::<Vec<_>>()
758-
.join(", ")
752+
self.fields().map(|f| f.name.as_str()).join(", ")
759753
));
760754
}
761755
Ok(())

0 commit comments

Comments
 (0)