Move new luau builtin options struct to where others are, reduce usage of unwrap

This commit is contained in:
Filip Tibell 2023-08-10 15:13:18 -05:00
parent 0a8773dc04
commit 768aadc225
No known key found for this signature in database
4 changed files with 123 additions and 108 deletions

View file

@ -1,102 +1,12 @@
use mlua::prelude::*; use mlua::prelude::*;
use mlua::Compiler as LuaCompiler;
use crate::lune::lua::table::TableBuilder; use crate::lune::lua::{
luau::{LuauCompileOptions, LuauLoadOptions},
table::TableBuilder,
};
const DEFAULT_DEBUG_NAME: &str = "luau.load(...)";
const BYTECODE_ERROR_BYTE: u8 = 0; const BYTECODE_ERROR_BYTE: u8 = 0;
struct CompileOptions {
pub optimization_level: u8,
pub coverage_level: u8,
pub debug_level: u8,
}
impl Default for CompileOptions {
fn default() -> Self {
Self {
optimization_level: 1,
coverage_level: 0,
debug_level: 1,
}
}
}
impl<'lua> FromLua<'lua> for CompileOptions {
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
Ok(match value {
LuaValue::Nil => Self {
optimization_level: 1,
coverage_level: 0,
debug_level: 1,
},
LuaValue::Table(t) => {
let optimization_level: Option<u8> = t.get("optimizationLevel")?;
let coverage_level: Option<u8> = t.get("coverageLevel")?;
let debug_level: Option<u8> = t.get("debugLevel")?;
Self {
optimization_level: optimization_level.unwrap_or(1),
coverage_level: coverage_level.unwrap_or(0),
debug_level: debug_level.unwrap_or(1),
}
}
_ => {
return Err(LuaError::FromLuaConversionError {
from: value.type_name(),
to: "CompileOptions",
message: Some(format!(
"Invalid compile options - expected table, got {}",
value.type_name()
)),
})
}
})
}
}
struct LoadOptions {
pub debug_name: String,
}
impl Default for LoadOptions {
fn default() -> Self {
Self {
debug_name: DEFAULT_DEBUG_NAME.to_string(),
}
}
}
impl<'lua> FromLua<'lua> for LoadOptions {
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
Ok(match value {
LuaValue::Nil => Self {
debug_name: DEFAULT_DEBUG_NAME.to_string(),
},
LuaValue::Table(t) => {
let debug_name: Option<String> = t.get("debugName")?;
Self {
debug_name: debug_name.unwrap_or(DEFAULT_DEBUG_NAME.to_string()),
}
}
LuaValue::String(s) => Self {
debug_name: s.to_str()?.to_string(),
},
_ => {
return Err(LuaError::FromLuaConversionError {
from: value.type_name(),
to: "LoadOptions",
message: Some(format!(
"Invalid load options - expected string or table, got {}",
value.type_name()
)),
})
}
})
}
}
pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> { pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
TableBuilder::new(lua)? TableBuilder::new(lua)?
.with_function("compile", compile_source)? .with_function("compile", compile_source)?
@ -106,29 +16,24 @@ pub fn create(lua: &'static Lua) -> LuaResult<LuaTable> {
fn compile_source<'lua>( fn compile_source<'lua>(
lua: &'lua Lua, lua: &'lua Lua,
(source, options): (LuaString<'lua>, CompileOptions), (source, options): (LuaString<'lua>, LuauCompileOptions),
) -> LuaResult<LuaString<'lua>> { ) -> LuaResult<LuaString<'lua>> {
let source_bytecode_bytes = LuaCompiler::default() let bytecode = options.into_compiler().compile(source);
.set_optimization_level(options.optimization_level)
.set_coverage_level(options.coverage_level)
.set_debug_level(options.debug_level)
.compile(source);
let first_byte = source_bytecode_bytes.first().unwrap(); match bytecode.first() {
Some(&BYTECODE_ERROR_BYTE) => Err(LuaError::RuntimeError(
match *first_byte { String::from_utf8_lossy(&bytecode).into_owned(),
BYTECODE_ERROR_BYTE => Err(LuaError::RuntimeError(
String::from_utf8(source_bytecode_bytes).unwrap(),
)), )),
_ => lua.create_string(source_bytecode_bytes), Some(_) => lua.create_string(bytecode),
None => panic!("Compiling resulted in empty bytecode"),
} }
} }
fn load_source<'a>( fn load_source<'a>(
lua: &'static Lua, lua: &'static Lua,
(source, options): (LuaString<'a>, LoadOptions), (source, options): (LuaString<'a>, LuauLoadOptions),
) -> LuaResult<LuaFunction<'a>> { ) -> LuaResult<LuaFunction<'a>> {
lua.load(source.to_str()?.trim_start()) lua.load(source.as_bytes())
.set_name(options.debug_name) .set_name(options.debug_name)
.into_function() .into_function()
} }

3
src/lune/lua/luau/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod options;
pub use options::{LuauCompileOptions, LuauLoadOptions};

View file

@ -0,0 +1,106 @@
use mlua::prelude::*;
use mlua::Compiler as LuaCompiler;
const DEFAULT_DEBUG_NAME: &str = "luau.load(...)";
pub struct LuauCompileOptions {
pub(crate) optimization_level: u8,
pub(crate) coverage_level: u8,
pub(crate) debug_level: u8,
}
impl LuauCompileOptions {
pub fn into_compiler(self) -> LuaCompiler {
LuaCompiler::default()
.set_optimization_level(self.optimization_level)
.set_coverage_level(self.coverage_level)
.set_debug_level(self.debug_level)
}
}
impl Default for LuauCompileOptions {
fn default() -> Self {
// NOTE: This is the same as LuaCompiler::default() values, but they are
// not accessible from outside of mlua so we need to recreate them here.
Self {
optimization_level: 1,
coverage_level: 0,
debug_level: 1,
}
}
}
impl<'lua> FromLua<'lua> for LuauCompileOptions {
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
Ok(match value {
LuaValue::Nil => Self::default(),
LuaValue::Table(t) => {
let mut options = Self::default();
if let Some(optimization_level) = t.get("optimizationLevel")? {
options.optimization_level = optimization_level;
}
if let Some(coverage_level) = t.get("coverageLevel")? {
options.coverage_level = coverage_level;
}
if let Some(debug_level) = t.get("debugLevel")? {
options.debug_level = debug_level;
}
options
}
_ => {
return Err(LuaError::FromLuaConversionError {
from: value.type_name(),
to: "CompileOptions",
message: Some(format!(
"Invalid compile options - expected table, got {}",
value.type_name()
)),
})
}
})
}
}
pub struct LuauLoadOptions {
pub(crate) debug_name: String,
}
impl Default for LuauLoadOptions {
fn default() -> Self {
Self {
debug_name: DEFAULT_DEBUG_NAME.to_string(),
}
}
}
impl<'lua> FromLua<'lua> for LuauLoadOptions {
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
Ok(match value {
LuaValue::Nil => Self::default(),
LuaValue::Table(t) => {
let mut options = Self::default();
if let Some(debug_name) = t.get("debugName")? {
options.debug_name = debug_name;
}
options
}
LuaValue::String(s) => Self {
debug_name: s.to_string_lossy().to_string(),
},
_ => {
return Err(LuaError::FromLuaConversionError {
from: value.type_name(),
to: "LoadOptions",
message: Some(format!(
"Invalid load options - expected string or table, got {}",
value.type_name()
)),
})
}
})
}
}

View file

@ -2,6 +2,7 @@ mod create;
pub mod async_ext; pub mod async_ext;
pub mod fs; pub mod fs;
pub mod luau;
pub mod net; pub mod net;
pub mod process; pub mod process;
pub mod serde; pub mod serde;