compile_time_lua_bind_hash/
lib.rs1extern 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}