Skip to main content

thisconfig_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{DeriveInput, Error, Expr, Lit, Meta, parse_macro_input};
4
5#[proc_macro_attribute]
6pub fn config(args: TokenStream, input: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(input as DeriveInput);
8
9    match config_impl(args, &input) {
10        Ok(tokens) => tokens,
11        Err(err) => err.to_compile_error().into(),
12    }
13}
14
15fn config_impl(args: TokenStream, input: &DeriveInput) -> syn::Result<TokenStream> {
16    let name = &input.ident;
17    let meta = syn::parse::<Meta>(args)?;
18
19    let nv = meta.require_name_value().map_err(|_| {
20        Error::new_spanned(&meta, r#"expected format: #[config(key = "section_name")]"#)
21    })?;
22
23    if !nv.path.is_ident("key") {
24        return Err(Error::new_spanned(&nv.path, "expected `key` attribute"));
25    }
26
27    let Expr::Lit(expr_lit) = &nv.value else {
28        return Err(Error::new_spanned(
29            &nv.value,
30            "expected string literal for key",
31        ));
32    };
33
34    let Lit::Str(lit_str) = &expr_lit.lit else {
35        return Err(Error::new_spanned(
36            &expr_lit.lit,
37            "expected string literal for key",
38        ));
39    };
40
41    #[cfg(feature = "axum")]
42    let expanded = quote! {
43        #input
44
45        impl ::axum_config::ConfigItem for #name {
46            fn key() -> &'static str {
47                #lit_str
48            }
49        }
50    };
51
52    #[cfg(not(feature = "axum"))]
53    let expanded = quote! {
54        #input
55
56        impl ::thisconfig::ConfigItem for #name {
57            fn key() -> &'static str {
58                #lit_str
59            }
60        }
61    };
62
63    Ok(expanded.into())
64}