singletonum_derive/
lib.rs

1#[macro_use]
2extern crate quote;
3extern crate syn;
4extern crate proc_macro;
5#[macro_use]
6extern crate failure;
7extern crate heck;
8
9use failure::Error;
10use syn::Ident;
11use proc_macro::TokenStream;
12use quote::quote;
13use heck::ShoutySnakeCase;
14
15#[proc_macro_derive(Singleton)]
16pub fn singleton_derive(input: TokenStream) -> TokenStream {
17    // Construct a string representation of the type definition
18    let s = input.to_string();
19
20    // Parse the string representation
21    let ast = syn::parse_derive_input(&s).unwrap();
22
23    // Build the impl
24    let gen = impl_singleton(&ast);
25
26    // Return the generated impl
27    gen.parse().unwrap()
28}
29
30fn impl_singleton(ast: &syn::DeriveInput) -> quote::Tokens {
31    let name = &ast.ident;
32    let static_var_name = format!("{}_SINGLETON", name.as_ref().to_shouty_snake_case());
33    let static_var_ident = Ident::from(static_var_name);
34    quote! {
35        static #static_var_ident: singletonum::OnceCell<#name> = singletonum::OnceCell::INIT;
36
37        impl singletonum::Singleton for #name {
38            fn get_instance(init: &Self::Init) -> &'static Self {
39                #static_var_ident.get_or_init(|| Self::init(init))
40            }
41        }
42    }
43}