1use std::str::FromStr;
2
3use convert_case::{Boundary, Case, Casing};
4
5use crate::svd::BitRangeType;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum IdentifierFormat {
9 Camel,
13 Pascal,
17 Snake,
21 Constant,
25}
26
27impl FromStr for IdentifierFormat {
28 type Err = ();
29
30 fn from_str(s: &str) -> Result<Self, Self::Err> {
31 match s {
32 "Camel" => Ok(IdentifierFormat::Camel),
33 "Pascal" => Ok(IdentifierFormat::Pascal),
34 "Snake" => Ok(IdentifierFormat::Snake),
35 "Constant" => Ok(IdentifierFormat::Constant),
36 _ => Err(()),
37 }
38 }
39}
40
41pub fn change_case(s: &str, case: Option<IdentifierFormat>) -> String {
42 match case {
43 None => s.to_string(),
44 Some(case) => {
45 let boundary = [
46 Boundary::Underscore,
47 Boundary::Hyphen,
48 Boundary::Space,
49 Boundary::LowerUpper,
50 Boundary::UpperLower,
51 Boundary::Acronym,
52 ];
53
54 s.with_boundaries(&boundary)
55 .to_case(match case {
56 IdentifierFormat::Camel => Case::Camel,
57 IdentifierFormat::Pascal => Case::Pascal,
58 IdentifierFormat::Snake => Case::Snake,
59 IdentifierFormat::Constant => Case::UpperSnake,
60 })
61 .replace("%S", "%s")
62 }
63 }
64}
65
66#[derive(Clone, Copy, Debug, PartialEq, Eq)]
67pub enum NumberFormat {
68 UpperHex,
72 UpperHex8,
76 UpperHex16,
80 LowerHex,
84 LowerHex8,
88 LowerHex16,
92 Dec,
96 Bin,
100}
101
102impl FromStr for NumberFormat {
103 type Err = ();
104
105 fn from_str(s: &str) -> Result<Self, Self::Err> {
106 match s {
107 "UpperHex" => Ok(NumberFormat::UpperHex),
108 "UpperHex8" => Ok(NumberFormat::UpperHex8),
109 "UpperHex16" => Ok(NumberFormat::UpperHex16),
110 "LowerHex" => Ok(NumberFormat::LowerHex),
111 "LowerHex8" => Ok(NumberFormat::LowerHex8),
112 "LowerHex16" => Ok(NumberFormat::LowerHex16),
113 "Dec" => Ok(NumberFormat::Dec),
114 "Bin" => Ok(NumberFormat::Bin),
115 _ => Err(()),
116 }
117 }
118}
119
120pub fn format_number<T>(value: T, format: NumberFormat) -> String
121where
122 T: std::fmt::UpperHex
123 + std::fmt::LowerHex
124 + std::fmt::Display
125 + std::fmt::Binary
126 + Into<u64>
127 + Copy,
128{
129 match format {
130 NumberFormat::UpperHex => format!("{:#X}", value),
131 NumberFormat::UpperHex8 => format!("{:#010X}", value),
132 NumberFormat::UpperHex16 => {
133 if value.into() > u32::MAX as u64 {
134 format!("{:#018X}", value)
135 } else {
136 format!("{:#010X}", value)
137 }
138 }
139 NumberFormat::LowerHex => format!("{:#x}", value),
140 NumberFormat::LowerHex8 => format!("{:#010x}", value),
141 NumberFormat::LowerHex16 => {
142 if value.into() > u32::MAX as u64 {
143 format!("{:#018x}", value)
144 } else {
145 format!("{:#010x}", value)
146 }
147 }
148 NumberFormat::Dec => format!("{}", value),
149 NumberFormat::Bin => format!("{:#b}", value),
150 }
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Eq)]
154pub struct FieldBitRangeFormat(pub BitRangeType);
155
156impl FromStr for FieldBitRangeFormat {
157 type Err = ();
158
159 fn from_str(s: &str) -> Result<Self, Self::Err> {
160 match s {
161 "BitRange" => Ok(FieldBitRangeFormat(BitRangeType::BitRange)),
162 "OffsetWidth" => Ok(FieldBitRangeFormat(BitRangeType::OffsetWidth)),
163 "MsbLsb" => Ok(FieldBitRangeFormat(BitRangeType::MsbLsb)),
164 _ => Err(()),
165 }
166 }
167}
168
169#[derive(Clone, Copy, Debug, PartialEq, Eq)]
170#[non_exhaustive]
171pub enum Sorting {
173 Offset,
175 OffsetReversed,
177 Name,
179}
180
181impl Sorting {
182 fn from_parts(parts: &[&str]) -> Option<Self> {
183 if parts.contains(&"Offset") {
184 Some(Self::Offset)
185 } else if parts.contains(&"OffsetReversed") {
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)]
196pub enum DerivableSorting {
197 Unchanged(Option<Sorting>),
198 DeriveLast(Option<Sorting>),
199}
200
201impl 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
212impl 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
221impl Default for DerivableSorting {
222 fn default() -> Self {
223 Self::Unchanged(None)
224 }
225}
226
227#[derive(Clone, Copy, Debug, PartialEq, Eq)]
228pub enum RcSorting {
229 Unchanged(DerivableSorting),
230 RegistersFirst(DerivableSorting),
231 ClustersFirst(DerivableSorting),
232}
233
234impl Default for RcSorting {
235 fn default() -> Self {
236 Self::Unchanged(Default::default())
237 }
238}
239
240impl 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
256#[derive(Clone, Copy, Debug)]
257#[non_exhaustive]
258pub struct Config {
260 pub peripheral_name: Option<IdentifierFormat>,
268
269 pub peripheral_base_address: NumberFormat,
273
274 pub peripheral_sorting: DerivableSorting,
276
277 pub address_block_offset: NumberFormat,
281
282 pub address_block_size: NumberFormat,
286
287 pub interrupt_name: Option<IdentifierFormat>,
290
291 pub cluster_name: Option<IdentifierFormat>,
296
297 pub cluster_address_offset: NumberFormat,
301
302 pub register_cluster_sorting: RcSorting,
304
305 pub register_name: Option<IdentifierFormat>,
310
311 pub register_address_offset: NumberFormat,
315
316 pub register_size: NumberFormat,
320
321 pub register_reset_value: NumberFormat,
325
326 pub register_reset_mask: NumberFormat,
330
331 pub field_name: Option<IdentifierFormat>,
335
336 pub field_bit_range: Option<FieldBitRangeFormat>,
340
341 pub field_sorting: DerivableSorting,
343
344 pub enumerated_values_name: Option<IdentifierFormat>,
348
349 pub enumerated_value_name: Option<IdentifierFormat>,
352
353 pub enumerated_value_value: NumberFormat,
357
358 pub dim_dim: NumberFormat,
362
363 pub dim_increment: NumberFormat,
367
368 pub dim_array_index_header_enum_name: Option<IdentifierFormat>,
370}
371
372impl Default for Config {
373 fn default() -> Self {
374 Self {
375 peripheral_name: None,
376 peripheral_base_address: NumberFormat::UpperHex8,
377 peripheral_sorting: Default::default(),
378 address_block_offset: NumberFormat::UpperHex,
379 address_block_size: NumberFormat::UpperHex,
380 interrupt_name: None,
381 cluster_name: None,
382 cluster_address_offset: NumberFormat::UpperHex,
383 register_cluster_sorting: Default::default(),
384 register_name: None,
385 register_address_offset: NumberFormat::UpperHex,
386 register_size: NumberFormat::LowerHex,
387 register_reset_value: NumberFormat::UpperHex16,
388 register_reset_mask: NumberFormat::UpperHex16,
389 field_name: None,
390 field_bit_range: None,
391 field_sorting: Default::default(),
392 enumerated_values_name: None,
393 enumerated_value_name: None,
394 enumerated_value_value: NumberFormat::Dec,
395 dim_dim: NumberFormat::Dec,
396 dim_increment: NumberFormat::UpperHex,
397 dim_array_index_header_enum_name: None,
398 }
399 }
400}
401
402impl Config {
403 pub fn update(&mut self, name: &str, value: &str) {
407 match name {
408 "peripheral_name" => self.peripheral_name = Some(value.parse().unwrap()),
409 "peripheral_base_address" => self.peripheral_base_address = value.parse().unwrap(),
410 "peripheral_sorting" => self.peripheral_sorting = value.parse().unwrap(),
411 "address_block_offset" => self.address_block_offset = value.parse().unwrap(),
412 "address_block_size" => self.address_block_size = value.parse().unwrap(),
413 "interrupt_name" => self.interrupt_name = Some(value.parse().unwrap()),
414 "cluster_name" => self.cluster_name = Some(value.parse().unwrap()),
415 "cluster_address_offset" => self.cluster_address_offset = value.parse().unwrap(),
416 "register_cluster_sorting" => self.register_cluster_sorting = value.parse().unwrap(),
417 "register_name" => self.register_name = Some(value.parse().unwrap()),
418 "register_address_offset" => self.register_address_offset = value.parse().unwrap(),
419 "register_size" => self.register_size = value.parse().unwrap(),
420 "register_reset_value" => self.register_reset_value = value.parse().unwrap(),
421 "register_reset_mask" => self.register_reset_mask = value.parse().unwrap(),
422 "field_name" => self.field_name = Some(value.parse().unwrap()),
423 "field_bit_range" => self.field_bit_range = Some(value.parse().unwrap()),
424 "field_sorting" => self.field_sorting = value.parse().unwrap(),
425 "enumerated_values_name" => self.enumerated_values_name = Some(value.parse().unwrap()),
426 "enumerated_value_name" => self.enumerated_value_name = Some(value.parse().unwrap()),
427 "enumerated_value_value" => self.enumerated_value_value = value.parse().unwrap(),
428 "dim_dim" => self.dim_dim = value.parse().unwrap(),
429 "dim_increment" => self.dim_increment = value.parse().unwrap(),
430 "dim_array_index_header_enum_name" => {
431 self.dim_array_index_header_enum_name = Some(value.parse().unwrap())
432 }
433 _ => {
434 eprintln!("Unknown config key: {}", name);
435 }
436 }
437 }
438
439 pub fn peripheral_name(mut self, val: Option<IdentifierFormat>) -> Self {
441 self.peripheral_name = val;
442 self
443 }
444
445 pub fn peripheral_base_address(mut self, val: NumberFormat) -> Self {
449 self.peripheral_base_address = val;
450 self
451 }
452
453 pub fn peripheral_sorting(mut self, val: DerivableSorting) -> Self {
457 self.peripheral_sorting = val;
458 self
459 }
460
461 pub fn address_block_offset(mut self, val: NumberFormat) -> Self {
465 self.address_block_offset = val;
466 self
467 }
468
469 pub fn address_block_size(mut self, val: NumberFormat) -> Self {
473 self.address_block_size = val;
474 self
475 }
476
477 pub fn interrupt_name(mut self, val: Option<IdentifierFormat>) -> Self {
479 self.interrupt_name = val;
480 self
481 }
482
483 pub fn cluster_name(mut self, val: Option<IdentifierFormat>) -> Self {
485 self.cluster_name = val;
486 self
487 }
488
489 pub fn cluster_address_offset(mut self, val: NumberFormat) -> Self {
493 self.cluster_address_offset = val;
494 self
495 }
496
497 pub fn register_cluster_sorting(mut self, val: RcSorting) -> Self {
501 self.register_cluster_sorting = val;
502 self
503 }
504
505 pub fn register_name(mut self, val: Option<IdentifierFormat>) -> Self {
507 self.register_name = val;
508 self
509 }
510
511 pub fn register_address_offset(mut self, val: NumberFormat) -> Self {
515 self.register_address_offset = val;
516 self
517 }
518
519 pub fn register_size(mut self, val: NumberFormat) -> Self {
523 self.register_size = val;
524 self
525 }
526
527 pub fn register_reset_value(mut self, val: NumberFormat) -> Self {
531 self.register_reset_value = val;
532 self
533 }
534
535 pub fn register_reset_mask(mut self, val: NumberFormat) -> Self {
539 self.register_reset_mask = val;
540 self
541 }
542
543 pub fn field_name(mut self, val: Option<IdentifierFormat>) -> Self {
545 self.field_name = val;
546 self
547 }
548
549 pub fn field_bit_range(mut self, val: Option<FieldBitRangeFormat>) -> Self {
553 self.field_bit_range = val;
554 self
555 }
556
557 pub fn field_sorting(mut self, val: DerivableSorting) -> Self {
561 self.field_sorting = val;
562 self
563 }
564
565 pub fn enumerated_values_name(mut self, val: Option<IdentifierFormat>) -> Self {
567 self.enumerated_values_name = val;
568 self
569 }
570
571 pub fn enumerated_value_name(mut self, val: Option<IdentifierFormat>) -> Self {
573 self.enumerated_value_name = val;
574 self
575 }
576
577 pub fn enumerated_value_value(mut self, val: NumberFormat) -> Self {
581 self.enumerated_value_value = val;
582 self
583 }
584
585 pub fn dim_dim(mut self, val: NumberFormat) -> Self {
589 self.dim_dim = val;
590 self
591 }
592
593 pub fn dim_increment(mut self, val: NumberFormat) -> Self {
597 self.dim_increment = val;
598 self
599 }
600}