lazy_settings_macros/
lib.rs

1extern crate proc_macro;
2#[macro_use]
3extern crate quote;
4extern crate syn;
5
6use proc_macro::TokenStream;
7
8use darling::FromMeta;
9use syn::parse_macro_input;
10
11#[derive(Debug, FromMeta)]
12struct Args {
13    key: String,
14}
15
16#[proc_macro_attribute]
17pub fn settings(metadata: TokenStream, input: TokenStream) -> TokenStream {
18    let input_struct = parse_macro_input!(input as syn::ItemStruct);
19    let attr_args = parse_macro_input!(metadata as syn::AttributeArgs);
20    let args = Args::from_list(&attr_args).unwrap();
21    let struct_ident = input_struct.ident.clone();
22    let key = args.key.clone();
23    let uppercase_key = key.to_uppercase();
24    TokenStream::from(quote! {
25        #[derive(Debug, Clone, ::lazy_settings::serde::Deserialize, ::lazy_settings::getset_scoped::Getters)]
26        #[get]
27        #input_struct
28
29        impl #struct_ident {
30            pub fn get(instance_name: &str) -> Result<Self, ::lazy_settings::eyre::Report> {
31                static SINGLETON: ::lazy_settings::once_cell::sync::Lazy<::lazy_settings::parking_lot::RwLock<::std::collections::HashMap<String, #struct_ident>>> = ::once_cell::sync::Lazy::new(|| ::lazy_settings::parking_lot::RwLock::new(::std::collections::HashMap::default()));
32                {
33                    let singleton_ro = SINGLETON.read();
34                    if let Some(existing_settings) = singleton_ro.get(instance_name) {
35                        return Ok(existing_settings.clone())
36                    }
37                }
38                {
39                    let new_settings = ::lazy_settings::config::Config::builder()
40                        .add_source(::lazy_settings::config::Environment::with_prefix(
41                            format!("APP_{}_{}", #uppercase_key, instance_name.to_uppercase()).as_str(),
42                        ))
43                        .build()?;
44                    eprintln!("Initializing {} settings, instance name: {}", #key, instance_name);
45                    let new_settings: #struct_ident = ::lazy_settings::eyre::WrapErr::wrap_err(new_settings.try_deserialize(), "Cannot read settings.")?;
46                    let mut singleton_rw = SINGLETON.write();
47                    singleton_rw.insert(instance_name.to_string(), new_settings.clone());
48                    return Ok(new_settings)
49                }
50            }
51        }
52    })
53}