rdrive_macros/
lib.rs

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