1use proc_macro::TokenStream;
2use quote::{format_ident, quote};
3
4#[proc_macro]
5pub fn __mod_maker(input: TokenStream) -> TokenStream {
6 let mut _mod = syn::parse_macro_input!(input as syn::ItemMod);
7 let mut name = String::new();
8
9 for c in _mod.content.as_ref().unwrap().1.iter() {
10 if let syn::Item::Static(st) = c
11 && let syn::Expr::Struct(expr_struct) = st.expr.as_ref()
12 {
13 for field in &expr_struct.fields {
14 if let syn::Member::Named(ident) = &field.member
15 && *ident == "name"
16 && let syn::Expr::Group(expr_group) = &field.expr
17 && let syn::Expr::Lit(expr_lit) = expr_group.expr.as_ref()
18 && let syn::Lit::Str(lit_str) = &expr_lit.lit
19 {
20 name = lit_str.value();
21 }
22 }
23 }
24 }
25
26 name = rename(name.as_str());
27
28 let mod_name = name.to_lowercase();
29
30 _mod.ident = format_ident!("__mod_{}", mod_name);
31
32 for c in _mod.content.as_mut().unwrap().1.iter_mut() {
33 if let syn::Item::Static(st) = c {
34 st.ident = format_ident!("__DRIVER_{}", name.to_uppercase());
35 }
36 }
37
38 quote! { #_mod }.into()
39}
40
41fn rename(s: &str) -> String {
42 let mut result = String::with_capacity(s.len());
43 for (i, c) in s.chars().enumerate() {
44 if c.is_ascii_alphabetic() || c == '_' || (i > 0 && c.is_ascii_digit()) {
45 result.push(c);
46 } else {
47 result.push('_');
48 }
49 }
50 result
51}