use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use syn::{punctuated::Punctuated, Token};
use crate::{
command_enum_parsing::{Field, FunctionDeclaration, NamespacePath},
DataCommandEnum,
};
pub fn generate_add_lua_functions_to_globals(input: &DataCommandEnum) -> TokenStream2 {
fn turn_field_to_functions(
input: &Punctuated<Field, Token![,]>,
namespace_path: Option<&NamespacePath>,
) -> TokenStream2 {
input
.iter()
.map(|field| match field {
Field::Function(function) => generate_function_adder(function, namespace_path),
Field::Namespace(namespace) => {
let mut passed_namespace =
namespace_path.unwrap_or(&Default::default()).clone();
namespace
.path
.clone()
.into_iter()
.for_each(|val| passed_namespace.push(val));
turn_field_to_functions(&namespace.fields, Some(&passed_namespace))
}
})
.collect()
}
let function_adders: TokenStream2 = turn_field_to_functions(&input.fields, None);
quote! {
pub fn add_lua_functions_to_globals(
lua: mlua::Lua,
tx: tokio::sync::mpsc::Sender<Event>,
) -> mlua::Lua {
lua.set_app_data(tx);
let globals = lua.globals();
#function_adders
drop(globals);
lua
}
}
}
fn generate_function_adder(
field: &FunctionDeclaration,
namespace_path: Option<&NamespacePath>,
) -> TokenStream2 {
let field_ident = &field.name;
let function_ident = format_ident!("wrapped_lua_function_{}", field_ident);
let function_name = field_ident.to_string();
let setter = if let Some(namespace_path) = namespace_path {
let mut counter = 0;
let namespace_table_gen: TokenStream2 = namespace_path.iter().map(|path| {
let path = path.to_string();
counter += 1;
let mut set_function: TokenStream2 = Default::default();
if counter == namespace_path.len() {
set_function = quote! {
table.set(#function_name, #function_ident).expect(
"Setting a static global value should work"
);
};
}
quote! {
let table: mlua::Table = {
if table.contains_key(#path).expect("This check should work") {
let table2 = table.get(#path).expect("This was already checked");
table2
} else {
table.set(#path, lua.create_table().expect("This should also always work")).expect("Setting this value should work");
table.get(#path).expect("This was set, just above")
}
};
#set_function
}
}).collect();
quote! {
let table = &globals;
{
#namespace_table_gen
}
}
} else {
quote! {
globals.set(#function_name, #function_ident).expect(
"Setting a static global value should work"
);
}
};
quote! {
{
let #function_ident = lua.create_async_function(#field_ident).expect(
&format!(
"The function: `{}` should be defined",
#function_name
)
);
#setter
}
}
}