Skip to content

Commit b5e58ae

Browse files
bors[bot]burrbull
andauthored
Merge #220
220: sorting on encode r=Emilgardis a=burrbull Co-authored-by: Andrey Zgarbul <[email protected]>
2 parents 8ee1f61 + c187416 commit b5e58ae

File tree

8 files changed

+373
-22
lines changed

8 files changed

+373
-22
lines changed

svd-encoder/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## Unreleased
99

10+
- Add `Sorting` options to `Config`
11+
1012
## [v0.14.2] - 2022-12-19
1113

1214
- Fix typo in `headerDefinitionsPrefix`

svd-encoder/src/config.rs

Lines changed: 129 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use convert_case::{Boundary, Case, Casing};
44

55
use crate::svd::BitRangeType;
66

7-
#[derive(Clone, Copy, Debug)]
7+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
88
pub enum IdentifierFormat {
99
/// `Camel` case
1010
///
@@ -63,7 +63,7 @@ pub fn change_case(s: &str, case: Option<IdentifierFormat>) -> String {
6363
}
6464
}
6565

66-
#[derive(Clone, Copy, Debug)]
66+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6767
pub enum NumberFormat {
6868
/// `UpperHex` format
6969
///
@@ -150,7 +150,7 @@ where
150150
}
151151
}
152152

153-
#[derive(Clone, Copy, Debug)]
153+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
154154
pub struct FieldBitRangeFormat(pub BitRangeType);
155155

156156
impl FromStr for FieldBitRangeFormat {
@@ -166,6 +166,93 @@ impl FromStr for FieldBitRangeFormat {
166166
}
167167
}
168168

169+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
170+
#[non_exhaustive]
171+
/// Apply a kind of sorting
172+
pub enum Sorting {
173+
/// Sort by addresses of offsets
174+
Offset,
175+
/// Same as [`Sorting::Offset`], but reversed
176+
OffsetReversed,
177+
/// Sort by name
178+
Name,
179+
}
180+
181+
impl Sorting {
182+
fn from_parts(parts: &[&str]) -> Option<Self> {
183+
if parts.contains(&"Offset") {
184+
Some(Self::Offset)
185+
} else if parts.contains(&"OffsetReserved") {
186+
Some(Self::OffsetReversed)
187+
} else if parts.contains(&"Name") {
188+
Some(Self::Name)
189+
} else {
190+
None
191+
}
192+
}
193+
}
194+
195+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
196+
pub enum DerivableSorting {
197+
Unchanged(Option<Sorting>),
198+
DeriveLast(Option<Sorting>),
199+
}
200+
201+
impl DerivableSorting {
202+
fn from_parts(parts: &[&str]) -> Self {
203+
let sorting = Sorting::from_parts(parts);
204+
if parts.contains(&"DerivedLast") {
205+
Self::DeriveLast(sorting)
206+
} else {
207+
Self::Unchanged(sorting)
208+
}
209+
}
210+
}
211+
212+
impl FromStr for DerivableSorting {
213+
type Err = ();
214+
215+
fn from_str(s: &str) -> Result<Self, Self::Err> {
216+
let parts = s.split(',').collect::<Vec<_>>();
217+
Ok(DerivableSorting::from_parts(&parts))
218+
}
219+
}
220+
221+
impl Default for DerivableSorting {
222+
fn default() -> Self {
223+
Self::Unchanged(None)
224+
}
225+
}
226+
227+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
228+
pub enum RcSorting {
229+
Unchanged(DerivableSorting),
230+
RegistersFirst(DerivableSorting),
231+
ClustersFirst(DerivableSorting),
232+
}
233+
234+
impl Default for RcSorting {
235+
fn default() -> Self {
236+
Self::Unchanged(Default::default())
237+
}
238+
}
239+
240+
impl FromStr for RcSorting {
241+
type Err = ();
242+
243+
fn from_str(s: &str) -> Result<Self, Self::Err> {
244+
let parts = s.split(',').collect::<Vec<_>>();
245+
let derivable_sorting = DerivableSorting::from_parts(&parts);
246+
Ok(if parts.contains(&"RegistersFirst") {
247+
Self::RegistersFirst(derivable_sorting)
248+
} else if parts.contains(&"ClustersFirst") {
249+
Self::ClustersFirst(derivable_sorting)
250+
} else {
251+
Self::Unchanged(derivable_sorting)
252+
})
253+
}
254+
}
255+
169256
#[derive(Clone, Copy, Debug)]
170257
#[non_exhaustive]
171258
/// Advanced encoder options
@@ -184,6 +271,9 @@ pub struct Config {
184271
/// format: hex, dec
185272
pub peripheral_base_address: NumberFormat,
186273

274+
/// Sort peripherals in specified order
275+
pub peripheral_sorting: DerivableSorting,
276+
187277
/// Format of addressBlock's offset element
188278
///
189279
/// format: hex, dec
@@ -209,6 +299,9 @@ pub struct Config {
209299
/// format: hex, dec
210300
pub cluster_address_offset: NumberFormat,
211301

302+
/// Sort registers and clusters in specified order
303+
pub register_cluster_sorting: RcSorting,
304+
212305
/// Format of register's name-kind elements
213306
/// - `derivedFrom`
214307
/// - `name`
@@ -245,6 +338,9 @@ pub struct Config {
245338
/// `None` means keep the original bitRange
246339
pub field_bit_range: Option<FieldBitRangeFormat>,
247340

341+
/// Sort fields in specified order
342+
pub field_sorting: DerivableSorting,
343+
248344
/// Format of enumeratedValues's name-kind elements
249345
/// - `derivedFrom`
250346
/// - `name`
@@ -278,18 +374,21 @@ impl Default for Config {
278374
Self {
279375
peripheral_name: None,
280376
peripheral_base_address: NumberFormat::UpperHex8,
377+
peripheral_sorting: Default::default(),
281378
address_block_offset: NumberFormat::UpperHex,
282379
address_block_size: NumberFormat::UpperHex,
283380
interrupt_name: None,
284381
cluster_name: None,
285382
cluster_address_offset: NumberFormat::UpperHex,
383+
register_cluster_sorting: Default::default(),
286384
register_name: None,
287385
register_address_offset: NumberFormat::UpperHex,
288386
register_size: NumberFormat::LowerHex,
289387
register_reset_value: NumberFormat::UpperHex16,
290388
register_reset_mask: NumberFormat::UpperHex16,
291389
field_name: None,
292390
field_bit_range: None,
391+
field_sorting: Default::default(),
293392
enumerated_values_name: None,
294393
enumerated_value_name: None,
295394
enumerated_value_value: NumberFormat::Dec,
@@ -308,18 +407,21 @@ impl Config {
308407
match name {
309408
"peripheral_name" => self.peripheral_name = Some(value.parse().unwrap()),
310409
"peripheral_base_address" => self.peripheral_base_address = value.parse().unwrap(),
410+
"peripheral_sorting" => self.peripheral_sorting = value.parse().unwrap(),
311411
"address_block_offset" => self.address_block_offset = value.parse().unwrap(),
312412
"address_block_size" => self.address_block_size = value.parse().unwrap(),
313413
"interrupt_name" => self.interrupt_name = Some(value.parse().unwrap()),
314414
"cluster_name" => self.cluster_name = Some(value.parse().unwrap()),
315415
"cluster_address_offset" => self.cluster_address_offset = value.parse().unwrap(),
416+
"register_cluster_sorting" => self.register_cluster_sorting = value.parse().unwrap(),
316417
"register_name" => self.register_name = Some(value.parse().unwrap()),
317418
"register_address_offset" => self.register_address_offset = value.parse().unwrap(),
318419
"register_size" => self.register_size = value.parse().unwrap(),
319420
"register_reset_value" => self.register_reset_value = value.parse().unwrap(),
320421
"register_reset_mask" => self.register_reset_mask = value.parse().unwrap(),
321422
"field_name" => self.field_name = Some(value.parse().unwrap()),
322423
"field_bit_range" => self.field_bit_range = Some(value.parse().unwrap()),
424+
"field_sorting" => self.field_sorting = value.parse().unwrap(),
323425
"enumerated_values_name" => self.enumerated_values_name = Some(value.parse().unwrap()),
324426
"enumerated_value_name" => self.enumerated_value_name = Some(value.parse().unwrap()),
325427
"enumerated_value_value" => self.enumerated_value_value = value.parse().unwrap(),
@@ -348,6 +450,14 @@ impl Config {
348450
self
349451
}
350452

453+
/// Sort peripherals in specified order
454+
///
455+
/// `None` means keep the original order
456+
pub fn peripheral_sorting(mut self, val: DerivableSorting) -> Self {
457+
self.peripheral_sorting = val;
458+
self
459+
}
460+
351461
/// Format of addressBlock's offset element
352462
///
353463
/// format: hex, dec
@@ -384,6 +494,14 @@ impl Config {
384494
self
385495
}
386496

497+
/// Sort registers and clusters in specified order
498+
///
499+
/// `None` means keep the original order
500+
pub fn register_cluster_sorting(mut self, val: RcSorting) -> Self {
501+
self.register_cluster_sorting = val;
502+
self
503+
}
504+
387505
/// Format of register's name-kind elements
388506
pub fn register_name(mut self, val: Option<IdentifierFormat>) -> Self {
389507
self.register_name = val;
@@ -436,6 +554,14 @@ impl Config {
436554
self
437555
}
438556

557+
/// Sort fields in specified order
558+
///
559+
/// `None` means keep the original order
560+
pub fn field_sorting(mut self, val: DerivableSorting) -> Self {
561+
self.field_sorting = val;
562+
self
563+
}
564+
439565
/// Format of enumeratedValues's name-kind elements
440566
pub fn enumerated_values_name(mut self, val: Option<IdentifierFormat>) -> Self {
441567
self.enumerated_values_name = val;

svd-encoder/src/device.rs

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
use svd_rs::Peripheral;
2+
13
use super::{new_node, Config, Element, Encode, EncodeChildren, EncodeError, XMLNode};
2-
use crate::svd::Device;
4+
use crate::{
5+
config::{DerivableSorting, Sorting},
6+
svd::Device,
7+
};
38

49
impl Encode for Device {
510
type Error = EncodeError;
@@ -57,11 +62,19 @@ impl Encode for Device {
5762
.encode_with_config(config)?,
5863
);
5964

60-
let peripherals: Result<Vec<_>, _> = self
61-
.peripherals
62-
.iter()
63-
.map(|peripheral| peripheral.encode_node_with_config(config))
64-
.collect();
65+
let peripherals: Result<Vec<_>, _> =
66+
if config.peripheral_sorting == DerivableSorting::Unchanged(None) {
67+
self.peripherals
68+
.iter()
69+
.map(|peripheral| peripheral.encode_node_with_config(config))
70+
.collect()
71+
} else {
72+
sort_derived_peripherals(&self.peripherals, config.peripheral_sorting)
73+
.into_iter()
74+
.map(|peripheral| peripheral.encode_node_with_config(config))
75+
.collect()
76+
};
77+
6578
elem.children.push({
6679
let mut e = Element::new("peripherals");
6780
e.children = peripherals?;
@@ -80,3 +93,42 @@ impl Encode for Device {
8093
Ok(elem)
8194
}
8295
}
96+
97+
fn sort_peripherals(refs: &mut [&Peripheral], sorting: Option<Sorting>) {
98+
if let Some(sorting) = sorting {
99+
match sorting {
100+
Sorting::Offset => refs.sort_by_key(|p| p.base_address),
101+
Sorting::OffsetReversed => {
102+
refs.sort_by_key(|p| -(p.base_address as i32));
103+
}
104+
Sorting::Name => refs.sort_by_key(|p| &p.name),
105+
}
106+
}
107+
}
108+
109+
fn sort_derived_peripherals(
110+
peripherals: &[Peripheral],
111+
sorting: DerivableSorting,
112+
) -> Vec<&Peripheral> {
113+
match sorting {
114+
DerivableSorting::Unchanged(sorting) => {
115+
let mut refs = peripherals.iter().collect::<Vec<_>>();
116+
sort_peripherals(&mut refs, sorting);
117+
refs
118+
}
119+
DerivableSorting::DeriveLast(sorting) => {
120+
let mut common_refs = peripherals
121+
.iter()
122+
.filter(|p| p.derived_from.is_none())
123+
.collect::<Vec<_>>();
124+
let mut derived_refs = peripherals
125+
.iter()
126+
.filter(|p| p.derived_from.is_some())
127+
.collect::<Vec<_>>();
128+
sort_peripherals(&mut common_refs, sorting);
129+
sort_peripherals(&mut derived_refs, sorting);
130+
common_refs.extend(derived_refs);
131+
common_refs
132+
}
133+
}
134+
}

svd-encoder/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use svd_rs as svd;
66
use crate::svd::Device;
77
use xmltree::{Element, EmitterConfig, XMLNode};
88

9-
pub use crate::config::{Config, IdentifierFormat, NumberFormat};
9+
pub use crate::config::{
10+
Config, DerivableSorting, IdentifierFormat, NumberFormat, RcSorting, Sorting,
11+
};
1012

1113
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
1214
pub enum EncodeError {}

0 commit comments

Comments
 (0)