compile_time_lua_bind_hash/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::{quote, quote_spanned};
5use syn::{parse_macro_input, Lit, Expr, spanned::Spanned};
6
7fn lit_to_bytes(lit: &Lit) -> Option<Vec<u8>> {
8    match lit {
9        Lit::Str(lit_str) => {
10            Some(lit_str.value().into_bytes())
11        }
12        Lit::ByteStr(lit_str) => {
13            Some(lit_str.value())
14        }
15        _ => {
16            None
17        }
18    }
19}
20
21fn expr_to_bytes(expr: &Expr) -> Option<Vec<u8>> {
22    match expr {
23        Expr::Lit(lit) => lit_to_bytes(&lit.lit),
24        Expr::Path(path) => {
25            let ident = path.path.get_ident()?;
26            Some(Vec::from(ident.to_string().as_bytes()))
27        }
28        Expr::Group(group) => {
29            expr_to_bytes(&group.expr)
30        }
31        _ => None
32    }
33}
34
35use std::sync::atomic::{AtomicBool, Ordering};
36
37static EXIT: AtomicBool = AtomicBool::new(false);
38
39#[proc_macro]
40pub fn lua_bind_hash(input: TokenStream) -> TokenStream {
41    if EXIT.load(Ordering::SeqCst) {
42        return quote!{}.into();
43    }
44
45    let expr = parse_macro_input!(input as Expr);
46
47    match expr_to_bytes(&expr) {
48        Some(string) => {
49            let lua_bind_hash = lua_bind_hash::lua_bind_hash(&string);
50            
51            TokenStream::from(quote! {
52                (#lua_bind_hash)
53            })
54        }
55        None => {
56            let span = expr.span();
57            EXIT.store(true, Ordering::SeqCst);
58            panic!("Invalid input: '{:?}'", expr);
59            TokenStream::from(quote_spanned!{span =>
60                compile_error!("Invalid input");
61            })
62        }
63    }
64}