#![allow(clippy::cargo_common_metadata)] use mlua::prelude::*; use lune_utils::TableBuilder; mod options; use self::options::{LuauCompileOptions, LuauLoadOptions}; const BYTECODE_ERROR_BYTE: u8 = 0; /** Creates the `luau` standard library module. # Errors Errors when out of memory. */ pub fn module(lua: &Lua) -> LuaResult { TableBuilder::new(lua)? .with_function("compile", compile_source)? .with_function("load", load_source)? .build_readonly() } fn compile_source<'lua>( lua: &'lua Lua, (source, options): (LuaString<'lua>, LuauCompileOptions), ) -> LuaResult> { let bytecode = options.into_compiler().compile(source); match bytecode.first() { Some(&BYTECODE_ERROR_BYTE) => Err(LuaError::RuntimeError( String::from_utf8_lossy(&bytecode).into_owned(), )), Some(_) => lua.create_string(bytecode), None => panic!("Compiling resulted in empty bytecode"), } } fn load_source<'lua>( lua: &'lua Lua, (source, options): (LuaString<'lua>, LuauLoadOptions), ) -> LuaResult> { let mut chunk = lua.load(source.as_bytes()).set_name(options.debug_name); if let Some(environment) = options.environment { let environment_with_globals = lua.create_table()?; if let Some(meta) = environment.get_metatable() { environment_with_globals.set_metatable(Some(meta)); } for pair in lua.globals().pairs() { let (key, value): (LuaValue, LuaValue) = pair?; environment_with_globals.set(key, value)?; } for pair in environment.pairs() { let (key, value): (LuaValue, LuaValue) = pair?; environment_with_globals.set(key, value)?; } chunk = chunk.set_environment(environment_with_globals); } chunk.into_function() }