1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, ItemFn};
4
5#[proc_macro_attribute]
22pub fn loader(_: TokenStream, item: TokenStream) -> TokenStream {
23 let input = parse_macro_input!(item as ItemFn);
24 let loader = &input.sig.ident;
25 let result = quote! {
26 #input
27
28 #[no_mangle]
29 pub unsafe extern "C" fn bootstrap(bootstrap: *const locenv::api::BootstrapContext, api: *const locenv::api::ApiTable) -> std::os::raw::c_int {
30 if locenv::API_TABLE.is_null() {
31 locenv::API_TABLE = api;
32 }
33
34 let lua = (*bootstrap).lua;
35 let context = locenv::Context::new(bootstrap);
36
37 locenv::push_fn(lua, #loader, 0);
38
39 let raw = Box::into_raw(Box::new(context));
41 let ptr = std::mem::size_of::<*mut locenv::Context>();
42 let ud = ((*api).lua_newuserdatauv)(lua, ptr, 1);
43
44 ud.copy_from_nonoverlapping(std::mem::transmute(&raw), ptr);
45
46 if ((*api).aux_newmetatable)(lua, (*bootstrap).name) == 0 {
48 let context = Box::from_raw(raw);
49
50 locenv::pop(lua, 3); locenv::push_str(lua, &format!("someone already created a metatable named '{}'", context.module_name()));
52
53 return 1;
54 }
55
56 ((*api).lua_pushstring)(lua, b"__gc\0".as_ptr() as *const _);
57 ((*api).lua_pushstring)(lua, (*bootstrap).name);
58 ((*api).lua_pushcclosure)(lua, locenv::Context::finalize, 1);
59 ((*api).lua_settable)(lua, -3);
60 ((*api).lua_setmetatable)(lua, -2);
61
62 2
63 }
64 };
65
66 result.into()
67}