Skip to content

Commit

Permalink
Custom prefix/case/suffix for identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
burrbull committed Jan 2, 2024
1 parent 8deac04 commit d1f2458
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 86 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

- Custom prefix/case/suffix for identifiers

## [v0.31.3] - 2023-12-25

- Add `svd::Device` validation after parsing by `serde`
Expand Down
100 changes: 98 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use anyhow::{bail, Result};
use std::path::{Path, PathBuf};

#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
#[derive(Clone, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Config {
pub target: Target,
pub atomics: bool,
Expand All @@ -28,6 +27,7 @@ pub struct Config {
pub interrupt_link_section: Option<String>,
pub reexport_core_peripherals: bool,
pub reexport_interrupt: bool,
pub ident_formats: IdentFormats,
}

#[allow(clippy::upper_case_acronyms)]
Expand Down Expand Up @@ -116,3 +116,99 @@ impl SourceType {
.unwrap_or_default()
}
}

#[cfg_attr(
feature = "serde",
derive(serde::Deserialize),
serde(rename_all = "lowercase")
)]
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub enum Case {
#[default]
Constant,
Pascal,
Snake,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
pub struct IdentFormat {
pub case: Option<Case>,
pub prefix: String,
pub suffix: String,
}

impl IdentFormat {
pub fn case(mut self, case: Case) -> Self {
self.case = Some(case);
self
}
pub fn constant_case(mut self) -> Self {
self.case = Some(Case::Constant);
self
}
pub fn pascal_case(mut self) -> Self {
self.case = Some(Case::Pascal);
self
}
pub fn scake_case(mut self) -> Self {
self.case = Some(Case::Pascal);
self
}
pub fn prefix(mut self, prefix: &str) -> Self {
self.prefix = prefix.into();
self
}
pub fn suffix(mut self, suffix: &str) -> Self {
self.suffix = suffix.into();
self
}
pub fn parse(s: &str) -> Result<Self, ()> {
let mut it = s.split(":");
match (it.next(), it.next(), it.next(), it.next()) {
(Some(prefix), Some(case), Some(suffix), None) => {
let case = match case {
"C" | "CONSTANT" => Some(Case::Constant),
"P" | "Pascal" => Some(Case::Pascal),
"S" | "snake" => Some(Case::Snake),
"_" => None,
_ => return Err(()),
};
Ok(Self {
case,
prefix: prefix.into(),
suffix: suffix.into(),
})
}
_ => Err(()),
}
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(default))]
pub struct IdentFormats {
pub field_reader: IdentFormat,
pub field_writer: IdentFormat,
pub enum_name: IdentFormat,
pub enum_write_name: IdentFormat,
pub enum_value: IdentFormat,
pub interrupt: IdentFormat,
pub register_spec: IdentFormat,
pub peripheral: IdentFormat,
}

impl Default for IdentFormats {
fn default() -> Self {
Self {
field_reader: IdentFormat::default().constant_case().suffix("_R"),
field_writer: IdentFormat::default().constant_case().suffix("_W"),
enum_name: IdentFormat::default().constant_case().suffix("_A"),
enum_write_name: IdentFormat::default().constant_case().suffix("_AW"),
enum_value: IdentFormat::default().constant_case(),
interrupt: IdentFormat::default().constant_case(),
register_spec: IdentFormat::default().constant_case().suffix("_SPEC"),
peripheral: IdentFormat::default().constant_case(),
}
}
}
21 changes: 11 additions & 10 deletions src/generate/device.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::svd::{array::names, Device, Peripheral};
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};

use log::debug;
Expand All @@ -9,7 +9,7 @@ use std::io::Write;
use std::path::Path;

use crate::config::{Config, Target};
use crate::util::{self, ToSanitizedCase};
use crate::util::{self, ident, ToSanitizedCase};
use anyhow::{Context, Result};

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

let span = Span::call_site();
match p {
Peripheral::Single(_p) => {
let p_name = util::name_of(p, config.ignore_groups);
let p_snake = p_name.to_sanitized_snake_case();
let p = p_name.to_sanitized_constant_case();
let id = Ident::new(&p, Span::call_site());
let p_ty = ident(&p_name, &config.ident_formats.peripheral, span);
if config.feature_peripheral {
feature_attribute.extend(quote! { #[cfg(feature = #p_snake)] })
};
fields.extend(quote! {
#[doc = #p]
#[doc = #p_name]
#feature_attribute
pub #id: #id,
pub #p_ty: #p_ty,
});
exprs.extend(quote!(#feature_attribute #id: #id { _marker: PhantomData },));
exprs.extend(quote!(#feature_attribute #p_ty: #p_ty { _marker: PhantomData },));
}
Peripheral::Array(_p, dim_element) => {
let p_names: Vec<Cow<str>> = names(p, dim_element).map(|n| n.into()).collect();
let p = p_names.iter().map(|p| p.to_sanitized_constant_case());
let ids_f = p.clone().map(|p| Ident::new(&p, Span::call_site()));
let ids_f = p_names
.iter()
.map(|p| ident(p, &config.ident_formats.peripheral, span));
let ids_e = ids_f.clone();
let feature_attribute = p_names
.iter()
Expand All @@ -265,7 +266,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke
.collect::<Vec<_>>();
fields.extend(quote! {
#(
#[doc = #p]
#[doc = #p_names]
#feature_attribute
pub #ids_f: #ids_f,
)*
Expand Down
15 changes: 8 additions & 7 deletions src/generate/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::svd::Peripheral;
use proc_macro2::{Span, TokenStream};
use quote::quote;

use crate::util::{self, ToSanitizedCase};
use crate::util::{self, ident, ToSanitizedCase};
use crate::{Config, Target};
use anyhow::Result;

Expand Down Expand Up @@ -46,14 +46,15 @@ pub fn render(
// Current position in the vector table
let mut pos = 0;
let mut mod_items = TokenStream::new();
let span = Span::call_site();
for interrupt in &interrupts {
while pos < interrupt.0.value {
elements.extend(quote!(Vector { _reserved: 0 },));
pos += 1;
}
pos += 1;

let name_constant_case = interrupt.0.name.to_constant_case_ident(Span::call_site());
let i_ty = ident(&interrupt.0.name, &config.ident_formats.interrupt, span);
let description = format!(
"{} - {}",
interrupt.0.value,
Expand Down Expand Up @@ -89,25 +90,25 @@ pub fn render(
variants.extend(quote! {
#[doc = #description]
#feature_attribute
#name_constant_case = #value,
#i_ty = #value,
});

from_arms.extend(quote! {
#feature_attribute
#value => Ok(Interrupt::#name_constant_case),
#value => Ok(Interrupt::#i_ty),
});

if feature_attribute_flag {
elements.extend(quote! {
#not_feature_attribute
Vector { _reserved: 0 },
#feature_attribute
Vector { _handler: #name_constant_case },
Vector { _handler: #i_ty },
});
} else {
elements.extend(quote!(Vector { _handler: #name_constant_case },));
elements.extend(quote!(Vector { _handler: #i_ty },));
}
names.push(name_constant_case);
names.push(i_ty);
names_cfg_attr.push(feature_attribute);
}

Expand Down
32 changes: 16 additions & 16 deletions src/generate/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use quote::{quote, ToTokens};
use syn::{punctuated::Punctuated, Token};

use crate::util::{
self, name_to_ty, path_segment, type_path, unsuffixed, zst_type, FullName, ToSanitizedCase,
BITS_PER_BYTE,
self, ident, name_to_ty, path_segment, type_path, unsuffixed, zst_type, FullName,
ToSanitizedCase, BITS_PER_BYTE,
};
use anyhow::{anyhow, bail, Context, Result};

Expand All @@ -38,8 +38,8 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result

let name = util::name_of(&p, config.ignore_groups);
let span = Span::call_site();
let name_str = name.to_sanitized_constant_case();
let name_constant_case = Ident::new(&name_str, span);
let p_ty = ident(&name, &config.ident_formats.peripheral, span);
let name_str = p_ty.to_string();
let address = util::hex(p.base_address);
let description = util::respace(p.description.as_ref().unwrap_or(&p.name));

Expand Down Expand Up @@ -81,8 +81,8 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
for pi in svd::peripheral::expand(p, dim) {
let name = &pi.name;
let description = pi.description.as_deref().unwrap_or(&p.name);
let name_str = name.to_sanitized_constant_case();
let name_constant_case = Ident::new(name, span);
let p_ty = ident(name, &config.ident_formats.peripheral, span);
let name_str = p_ty.to_string();
let address = util::hex(pi.base_address);
let p_snake = name.to_sanitized_snake_case();
snake_names.push(p_snake.to_string());
Expand All @@ -94,13 +94,13 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
out.extend(quote! {
#[doc = #description]
#feature_attribute_n
pub struct #name_constant_case { _marker: PhantomData<*const ()> }
pub struct #p_ty { _marker: PhantomData<*const ()> }

#feature_attribute_n
unsafe impl Send for #name_constant_case {}
unsafe impl Send for #p_ty {}

#feature_attribute_n
impl #name_constant_case {
impl #p_ty {
///Pointer to the register block
pub const PTR: *const #base::RegisterBlock = #address as *const _;

Expand All @@ -114,7 +114,7 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
}

#feature_attribute_n
impl Deref for #name_constant_case {
impl Deref for #p_ty {
type Target = #base::RegisterBlock;

#[inline(always)]
Expand All @@ -124,7 +124,7 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
}

#feature_attribute_n
impl core::fmt::Debug for #name_constant_case {
impl core::fmt::Debug for #p_ty {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct(#name_str).finish()
}
Expand Down Expand Up @@ -155,13 +155,13 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
out.extend(quote! {
#[doc = #description]
#feature_attribute
pub struct #name_constant_case { _marker: PhantomData<*const ()> }
pub struct #p_ty { _marker: PhantomData<*const ()> }

#feature_attribute
unsafe impl Send for #name_constant_case {}
unsafe impl Send for #p_ty {}

#feature_attribute
impl #name_constant_case {
impl #p_ty {
///Pointer to the register block
pub const PTR: *const #base::RegisterBlock = #address as *const _;

Expand All @@ -175,7 +175,7 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
}

#feature_attribute
impl Deref for #name_constant_case {
impl Deref for #p_ty {
type Target = #base::RegisterBlock;

#[inline(always)]
Expand All @@ -185,7 +185,7 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result
}

#feature_attribute
impl core::fmt::Debug for #name_constant_case {
impl core::fmt::Debug for #p_ty {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct(#name_str).finish()
}
Expand Down
Loading

0 comments on commit d1f2458

Please sign in to comment.