Skip to content

Commit 1735fff

Browse files
committed
Custom prefix/case/suffix for identifiers
1 parent 8deac04 commit 1735fff

File tree

8 files changed

+245
-137
lines changed

8 files changed

+245
-137
lines changed

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](https://semver.org/).
77

88
## [Unreleased]
99

10+
- Custom prefix/case/suffix for identifiers
11+
1012
## [v0.31.3] - 2023-12-25
1113

1214
- Add `svd::Device` validation after parsing by `serde`

src/config.rs

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use anyhow::{bail, Result};
22
use std::path::{Path, PathBuf};
33

4-
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
4+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
55
#[derive(Clone, PartialEq, Eq, Debug, Default)]
6-
#[cfg_attr(feature = "serde", serde(default))]
76
pub struct Config {
87
pub target: Target,
98
pub atomics: bool,
@@ -28,6 +27,7 @@ pub struct Config {
2827
pub interrupt_link_section: Option<String>,
2928
pub reexport_core_peripherals: bool,
3029
pub reexport_interrupt: bool,
30+
pub ident_formats: IdentFormats,
3131
}
3232

3333
#[allow(clippy::upper_case_acronyms)]
@@ -116,3 +116,103 @@ impl SourceType {
116116
.unwrap_or_default()
117117
}
118118
}
119+
120+
#[cfg_attr(
121+
feature = "serde",
122+
derive(serde::Deserialize),
123+
serde(rename_all = "lowercase")
124+
)]
125+
#[derive(Clone, Debug, PartialEq, Eq, Default)]
126+
pub enum Case {
127+
#[default]
128+
Constant,
129+
Pascal,
130+
Snake,
131+
}
132+
133+
#[derive(Clone, Debug, Default, PartialEq, Eq)]
134+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
135+
pub struct IdentFormat {
136+
pub case: Option<Case>,
137+
pub prefix: String,
138+
pub suffix: String,
139+
}
140+
141+
impl IdentFormat {
142+
pub fn case(mut self, case: Case) -> Self {
143+
self.case = Some(case);
144+
self
145+
}
146+
pub fn constant_case(mut self) -> Self {
147+
self.case = Some(Case::Constant);
148+
self
149+
}
150+
pub fn pascal_case(mut self) -> Self {
151+
self.case = Some(Case::Pascal);
152+
self
153+
}
154+
pub fn scake_case(mut self) -> Self {
155+
self.case = Some(Case::Pascal);
156+
self
157+
}
158+
pub fn prefix(mut self, prefix: &str) -> Self {
159+
self.prefix = prefix.into();
160+
self
161+
}
162+
pub fn suffix(mut self, suffix: &str) -> Self {
163+
self.suffix = suffix.into();
164+
self
165+
}
166+
pub fn parse(s: &str) -> Result<Self, ()> {
167+
let mut it = s.split(":");
168+
match (it.next(), it.next(), it.next(), it.next()) {
169+
(Some(prefix), Some(case), Some(suffix), None) => {
170+
let case = match case {
171+
"C" | "CONSTANT" => Some(Case::Constant),
172+
"P" | "Pascal" => Some(Case::Pascal),
173+
"S" | "snake" => Some(Case::Snake),
174+
"_" => None,
175+
_ => return Err(()),
176+
};
177+
Ok(Self {
178+
case,
179+
prefix: prefix.into(),
180+
suffix: suffix.into(),
181+
})
182+
}
183+
_ => Err(()),
184+
}
185+
}
186+
}
187+
188+
#[derive(Clone, Debug, PartialEq, Eq)]
189+
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
190+
pub struct IdentFormats {
191+
pub field_reader: IdentFormat,
192+
pub field_writer: IdentFormat,
193+
pub enum_name: IdentFormat,
194+
pub enum_write_name: IdentFormat,
195+
pub enum_value: IdentFormat,
196+
pub interrupt: IdentFormat,
197+
pub cluster: IdentFormat,
198+
pub register: IdentFormat,
199+
pub register_spec: IdentFormat,
200+
pub peripheral: IdentFormat,
201+
}
202+
203+
impl Default for IdentFormats {
204+
fn default() -> Self {
205+
Self {
206+
field_reader: IdentFormat::default().constant_case().suffix("_R"),
207+
field_writer: IdentFormat::default().constant_case().suffix("_W"),
208+
enum_name: IdentFormat::default().constant_case().suffix("_A"),
209+
enum_write_name: IdentFormat::default().constant_case().suffix("_AW"),
210+
enum_value: IdentFormat::default().constant_case(),
211+
interrupt: IdentFormat::default().constant_case(),
212+
cluster: IdentFormat::default().constant_case(),
213+
register: IdentFormat::default().constant_case(),
214+
register_spec: IdentFormat::default().constant_case().suffix("_SPEC"),
215+
peripheral: IdentFormat::default().constant_case(),
216+
}
217+
}
218+
}

src/generate/device.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::svd::{array::names, Device, Peripheral};
2-
use proc_macro2::{Ident, Span, TokenStream};
2+
use proc_macro2::{Span, TokenStream};
33
use quote::{quote, ToTokens};
44

55
use log::debug;
@@ -9,7 +9,7 @@ use std::io::Write;
99
use std::path::Path;
1010

1111
use crate::config::{Config, Target};
12-
use crate::util::{self, ToSanitizedCase};
12+
use crate::util::{self, ident, ToSanitizedCase};
1313
use anyhow::{Context, Result};
1414

1515
use crate::generate::{interrupt, peripheral};
@@ -231,26 +231,27 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
231231
feature_attribute.extend(quote! { #[cfg(feature = #feature_name)] })
232232
};
233233

234+
let span = Span::call_site();
234235
match p {
235236
Peripheral::Single(_p) => {
236237
let p_name = util::name_of(p, config.ignore_groups);
237238
let p_snake = p_name.to_sanitized_snake_case();
238-
let p = p_name.to_sanitized_constant_case();
239-
let id = Ident::new(&p, Span::call_site());
239+
let p_ty = ident(&p_name, &config.ident_formats.peripheral, span);
240240
if config.feature_peripheral {
241241
feature_attribute.extend(quote! { #[cfg(feature = #p_snake)] })
242242
};
243243
fields.extend(quote! {
244-
#[doc = #p]
244+
#[doc = #p_name]
245245
#feature_attribute
246-
pub #id: #id,
246+
pub #p_ty: #p_ty,
247247
});
248-
exprs.extend(quote!(#feature_attribute #id: #id { _marker: PhantomData },));
248+
exprs.extend(quote!(#feature_attribute #p_ty: #p_ty { _marker: PhantomData },));
249249
}
250250
Peripheral::Array(_p, dim_element) => {
251251
let p_names: Vec<Cow<str>> = names(p, dim_element).map(|n| n.into()).collect();
252-
let p = p_names.iter().map(|p| p.to_sanitized_constant_case());
253-
let ids_f = p.clone().map(|p| Ident::new(&p, Span::call_site()));
252+
let ids_f = p_names
253+
.iter()
254+
.map(|p| ident(p, &config.ident_formats.peripheral, span));
254255
let ids_e = ids_f.clone();
255256
let feature_attribute = p_names
256257
.iter()
@@ -265,7 +266,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
265266
.collect::<Vec<_>>();
266267
fields.extend(quote! {
267268
#(
268-
#[doc = #p]
269+
#[doc = #p_names]
269270
#feature_attribute
270271
pub #ids_f: #ids_f,
271272
)*

src/generate/interrupt.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::svd::Peripheral;
55
use proc_macro2::{Span, TokenStream};
66
use quote::quote;
77

8-
use crate::util::{self, ToSanitizedCase};
8+
use crate::util::{self, ident, ToSanitizedCase};
99
use crate::{Config, Target};
1010
use anyhow::Result;
1111

@@ -46,14 +46,15 @@ pub fn render(
4646
// Current position in the vector table
4747
let mut pos = 0;
4848
let mut mod_items = TokenStream::new();
49+
let span = Span::call_site();
4950
for interrupt in &interrupts {
5051
while pos < interrupt.0.value {
5152
elements.extend(quote!(Vector { _reserved: 0 },));
5253
pos += 1;
5354
}
5455
pos += 1;
5556

56-
let name_constant_case = interrupt.0.name.to_constant_case_ident(Span::call_site());
57+
let i_ty = ident(&interrupt.0.name, &config.ident_formats.interrupt, span);
5758
let description = format!(
5859
"{} - {}",
5960
interrupt.0.value,
@@ -89,25 +90,25 @@ pub fn render(
8990
variants.extend(quote! {
9091
#[doc = #description]
9192
#feature_attribute
92-
#name_constant_case = #value,
93+
#i_ty = #value,
9394
});
9495

9596
from_arms.extend(quote! {
9697
#feature_attribute
97-
#value => Ok(Interrupt::#name_constant_case),
98+
#value => Ok(Interrupt::#i_ty),
9899
});
99100

100101
if feature_attribute_flag {
101102
elements.extend(quote! {
102103
#not_feature_attribute
103104
Vector { _reserved: 0 },
104105
#feature_attribute
105-
Vector { _handler: #name_constant_case },
106+
Vector { _handler: #i_ty },
106107
});
107108
} else {
108-
elements.extend(quote!(Vector { _handler: #name_constant_case },));
109+
elements.extend(quote!(Vector { _handler: #i_ty },));
109110
}
110-
names.push(name_constant_case);
111+
names.push(i_ty);
111112
names_cfg_attr.push(feature_attribute);
112113
}
113114

0 commit comments

Comments
 (0)