svd_encoder/
config.rs

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` case
10    ///
11    /// `aCamelCaseExample`
12    Camel,
13    /// `Pascal` case
14    ///
15    /// `APascalCaseExample`
16    Pascal,
17    /// `Snake` case
18    ///
19    /// `a_snake_case_example`
20    Snake,
21    /// `Constant` case
22    ///
23    /// `A_CONSTANT_CASE_EXAMPLE`
24    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` format
69    ///
70    /// `0xABCD`
71    UpperHex,
72    /// `UpperHex8` format
73    ///
74    /// `0x0000ABCD`
75    UpperHex8,
76    /// `UpperHex16` format
77    ///
78    /// `0x0000ABCD` `0x0000000123456789`
79    UpperHex16,
80    /// `LowerHex` format
81    ///
82    /// `0xabcdef`
83    LowerHex,
84    /// `LowerHex8` format
85    ///
86    /// `0x0000abcd`
87    LowerHex8,
88    /// `LowerHex16` format
89    ///
90    /// `0x0000abcd` `0x0000000123456789`
91    LowerHex16,
92    /// `Dec` format
93    ///
94    /// `12345`
95    Dec,
96    /// `Bin`
97    ///
98    /// `0b10101010`
99    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]
171/// Apply a kind of sorting
172pub 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
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]
258/// Advanced encoder options
259pub struct Config {
260    /// Format of peripheral's name-kind elements
261    /// - `derivedFrom`
262    /// - `name`
263    /// - `alternatePeripheral`
264    /// - `prependToName`
265    /// - `appendToName`
266    /// - `headerStructName`
267    pub peripheral_name: Option<IdentifierFormat>,
268
269    /// Format of peripheral's baseAddress element
270    ///
271    /// format: hex, dec
272    pub peripheral_base_address: NumberFormat,
273
274    /// Sort peripherals in specified order
275    pub peripheral_sorting: DerivableSorting,
276
277    /// Format of addressBlock's offset element
278    ///
279    /// format: hex, dec
280    pub address_block_offset: NumberFormat,
281
282    /// Format of addressBlock's size element
283    ///
284    /// format: hex, dec
285    pub address_block_size: NumberFormat,
286
287    /// Format of interrupt's name-kind elements
288    /// - `name`
289    pub interrupt_name: Option<IdentifierFormat>,
290
291    /// Format of cluster's name-kind elements
292    /// - `derivedFrom`
293    /// - `name`
294    /// - `alternateCluster`
295    pub cluster_name: Option<IdentifierFormat>,
296
297    /// Format of cluster's addressOffset element
298    ///
299    /// format: hex, dec
300    pub cluster_address_offset: NumberFormat,
301
302    /// Sort registers and clusters in specified order
303    pub register_cluster_sorting: RcSorting,
304
305    /// Format of register's name-kind elements
306    /// - `derivedFrom`
307    /// - `name`
308    /// - `alternateRegister`
309    pub register_name: Option<IdentifierFormat>,
310
311    /// Format of register's addressOffset element
312    ///
313    /// format: hex, dec
314    pub register_address_offset: NumberFormat,
315
316    /// Format of register's size element
317    ///
318    /// format: hex, dec
319    pub register_size: NumberFormat,
320
321    /// Format of register's resetValue element
322    ///
323    /// format: hex, dec
324    pub register_reset_value: NumberFormat,
325
326    /// Format of register's resetMask element
327    ///
328    /// format: hex, dec
329    pub register_reset_mask: NumberFormat,
330
331    /// Format of field's name-kind elements
332    /// - `derivedFrom`
333    /// - `name`
334    pub field_name: Option<IdentifierFormat>,
335
336    /// Format of field's bitRange
337    ///
338    /// `None` means keep the original bitRange
339    pub field_bit_range: Option<FieldBitRangeFormat>,
340
341    /// Sort fields in specified order
342    pub field_sorting: DerivableSorting,
343
344    /// Format of enumeratedValues's name-kind elements
345    /// - `derivedFrom`
346    /// - `name`
347    pub enumerated_values_name: Option<IdentifierFormat>,
348
349    /// Format of enumeratedValue's name-kind elements
350    /// - `name`
351    pub enumerated_value_name: Option<IdentifierFormat>,
352
353    /// Format of enumeratedValue's value element
354    ///
355    /// format: hex, dec, bing
356    pub enumerated_value_value: NumberFormat,
357
358    /// Format of dim's dim element
359    ///
360    /// format: hex, dec
361    pub dim_dim: NumberFormat,
362
363    /// Format of dim's dimIncrement element
364    ///
365    /// format: hex, dec
366    pub dim_increment: NumberFormat,
367
368    /// Format of dimArrayIndex's headerEnumName element
369    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    /// Update the config with given name and value
404    ///
405    /// panic if the value is not valid
406    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    /// Format of peripheral's name-kind elements
440    pub fn peripheral_name(mut self, val: Option<IdentifierFormat>) -> Self {
441        self.peripheral_name = val;
442        self
443    }
444
445    /// Format of peripheral's baseAddress element
446    ///
447    /// format: hex, dec
448    pub fn peripheral_base_address(mut self, val: NumberFormat) -> Self {
449        self.peripheral_base_address = val;
450        self
451    }
452
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
461    /// Format of addressBlock's offset element
462    ///
463    /// format: hex, dec
464    pub fn address_block_offset(mut self, val: NumberFormat) -> Self {
465        self.address_block_offset = val;
466        self
467    }
468
469    /// Format of addressBlock's size element
470    ///
471    /// format: hex, dec
472    pub fn address_block_size(mut self, val: NumberFormat) -> Self {
473        self.address_block_size = val;
474        self
475    }
476
477    /// Format of interrupt's name-kind elements
478    pub fn interrupt_name(mut self, val: Option<IdentifierFormat>) -> Self {
479        self.interrupt_name = val;
480        self
481    }
482
483    /// Format of cluster's name-kind elements
484    pub fn cluster_name(mut self, val: Option<IdentifierFormat>) -> Self {
485        self.cluster_name = val;
486        self
487    }
488
489    /// Format of cluster's addressOffset element
490    ///
491    /// format: hex, dec
492    pub fn cluster_address_offset(mut self, val: NumberFormat) -> Self {
493        self.cluster_address_offset = val;
494        self
495    }
496
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
505    /// Format of register's name-kind elements
506    pub fn register_name(mut self, val: Option<IdentifierFormat>) -> Self {
507        self.register_name = val;
508        self
509    }
510
511    /// Format of register's addressOffset element
512    ///
513    /// format: hex, dec
514    pub fn register_address_offset(mut self, val: NumberFormat) -> Self {
515        self.register_address_offset = val;
516        self
517    }
518
519    /// Format of register's size element
520    ///
521    /// format: hex, dec
522    pub fn register_size(mut self, val: NumberFormat) -> Self {
523        self.register_size = val;
524        self
525    }
526
527    /// Format of register's resetValue element
528    ///
529    /// format: hex, dec
530    pub fn register_reset_value(mut self, val: NumberFormat) -> Self {
531        self.register_reset_value = val;
532        self
533    }
534
535    /// Format of register's resetMask element
536    ///
537    /// format: hex, dec
538    pub fn register_reset_mask(mut self, val: NumberFormat) -> Self {
539        self.register_reset_mask = val;
540        self
541    }
542
543    /// Format of field's name-kind elements
544    pub fn field_name(mut self, val: Option<IdentifierFormat>) -> Self {
545        self.field_name = val;
546        self
547    }
548
549    /// Format of field's bitRange
550    ///
551    /// `None` means keep the original bitRange
552    pub fn field_bit_range(mut self, val: Option<FieldBitRangeFormat>) -> Self {
553        self.field_bit_range = val;
554        self
555    }
556
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
565    /// Format of enumeratedValues's name-kind elements
566    pub fn enumerated_values_name(mut self, val: Option<IdentifierFormat>) -> Self {
567        self.enumerated_values_name = val;
568        self
569    }
570
571    /// Format of enumeratedValue's name-kind elements
572    pub fn enumerated_value_name(mut self, val: Option<IdentifierFormat>) -> Self {
573        self.enumerated_value_name = val;
574        self
575    }
576
577    /// Format of enumeratedValue's value element
578    ///
579    /// format: hex, dec, bing
580    pub fn enumerated_value_value(mut self, val: NumberFormat) -> Self {
581        self.enumerated_value_value = val;
582        self
583    }
584
585    /// Format of dim's dim element
586    ///
587    /// format: hex, dec
588    pub fn dim_dim(mut self, val: NumberFormat) -> Self {
589        self.dim_dim = val;
590        self
591    }
592
593    /// Format of dim's dimIncrement element
594    ///
595    /// format: hex, dec
596    pub fn dim_increment(mut self, val: NumberFormat) -> Self {
597        self.dim_increment = val;
598        self
599    }
600}