#![allow(non_snake_case)]
pub use luau_src::vm as raw;
mod types;
pub use types::*;
use super::prelude::*;
pub struct LuaError(i32);
#[derive(Debug, Error)]
pub enum LoadError {
#[error("Failed to convert &str to proper null terminated string (*const char)")]
ConversionError(std::ffi::NulError),
#[error("Runtime lua error. See https://github.com/Roblox/luau/blob/f1649a43cdf7dd9e41496913672e82b30c067234/VM/include/lua.h#L26")]
LuaError(i32), }
impl Luau {
#[inline(always)]
pub fn new() -> Luau {
Self(unsafe { raw::luaL_newstate() })
}
pub fn pcall(
&self,
nargs: i32,
nresults: i32,
errfunc: i32,
) -> Result<(), (i32, &'static str)> {
let res = unsafe { raw::lua_pcall(self.0, nargs, nresults, errfunc) };
match res {
raw::LUA_OK => Ok(()), status => {
let err = match status {
1 => Ok("Thread exited unexpectedly"),
_ => unsafe {
let raw_str = raw::luaL_tolstring(self.0, -1, std::ptr::null_mut());
CStr::from_ptr(raw_str).to_str()
},
};
Err((status, err.unwrap_or("Unknown")))
}
}
}
pub fn load<S: AsRef<[u8]>>(
&self,
chunk_name: &str,
bytecode: S,
env: Option<c_int>,
) -> Result<(), LoadError> {
let chunk_name = CString::new(chunk_name).map_err(LoadError::ConversionError)?;
let result = unsafe {
let bc = bytecode.as_ref();
raw::luau_load(
self.0,
chunk_name.as_ptr(),
bc.as_ptr() as _,
bc.len(),
env.unwrap_or(0),
)
};
match result {
raw::LUA_OK => Ok(()), other => Err(LoadError::LuaError(other)),
}
}
pub fn checkoption(&self, arg: i32, def: &str, lst: &[&str]) -> Result<i32, NulError> {
let def = CString::new(def)?;
let lst: Vec<CString> = lst.iter().map(|&s| CString::new(s).unwrap()).collect();
let lst_ptrs: Vec<*const i8> = lst.iter().map(|s| s.as_ptr()).collect();
Ok(unsafe { raw::luaL_checkoption(self.0, arg, def.as_ptr(), lst_ptrs.as_ptr()) })
}
}