Initial Luau support
This commit is contained in:
parent
6dc127f4eb
commit
c322e028e2
|
@ -9,7 +9,7 @@ jobs:
|
|||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
rust: [stable]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
|
@ -108,7 +108,7 @@ jobs:
|
|||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
rust: [stable, nightly]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luajit52]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luajit52, luau]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
|
@ -144,7 +144,7 @@ jobs:
|
|||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
rust: [nightly]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
|
@ -228,7 +228,7 @@ jobs:
|
|||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
||||
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
|
|
|
@ -34,7 +34,7 @@ lua52 = []
|
|||
lua51 = []
|
||||
luajit = []
|
||||
luajit52 = ["luajit"]
|
||||
luau = ["luau-src"]
|
||||
luau = ["luau0-src"]
|
||||
vendored = ["lua-src", "luajit-src"]
|
||||
module = ["mlua_derive"]
|
||||
async = ["futures-core", "futures-task", "futures-util"]
|
||||
|
@ -59,7 +59,7 @@ cc = { version = "1.0" }
|
|||
pkg-config = { version = "0.3.17" }
|
||||
lua-src = { version = ">= 540.0.0, < 550.0.0", optional = true }
|
||||
luajit-src = { version = ">= 210.3.1, < 220.0.0", optional = true }
|
||||
luau-src = { version = "1", optional = true }
|
||||
luau0-src = { version = "1", optional = true, git = "https://github.com/khvzak/luau-src-rs.git" }
|
||||
|
||||
[dev-dependencies]
|
||||
rustyline = "9.0"
|
||||
|
|
|
@ -18,7 +18,7 @@ pub fn probe_lua() -> Option<PathBuf> {
|
|||
builder.build()
|
||||
};
|
||||
#[cfg(feature = "luau")]
|
||||
let artifacts = luau_src::Build::new().build();
|
||||
let artifacts = luau0_src::Build::new().build();
|
||||
|
||||
#[cfg(not(feature = "module"))]
|
||||
artifacts.print_cargo_metadata();
|
||||
|
|
|
@ -17,6 +17,9 @@ use super::lua52::*;
|
|||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
use super::lua51::*;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
use super::luau::*;
|
||||
|
||||
unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) {
|
||||
while a < b {
|
||||
lua_pushvalue(L, a);
|
||||
|
@ -31,6 +34,7 @@ unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) {
|
|||
const COMPAT53_LEVELS1: c_int = 12; // size of the first part of the stack
|
||||
const COMPAT53_LEVELS2: c_int = 10; // size of the second part of the stack
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int {
|
||||
let mut ar: lua_Debug = mem::zeroed();
|
||||
let (mut li, mut le) = (1, 1);
|
||||
|
@ -51,6 +55,27 @@ unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int {
|
|||
le - 1
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int {
|
||||
let mut ar: lua_Debug = mem::zeroed();
|
||||
let (mut li, mut le) = (1, 1);
|
||||
// find an upper bound
|
||||
while lua_getinfo(L, le, cstr!(""), &mut ar) != 0 {
|
||||
li = le;
|
||||
le *= 2;
|
||||
}
|
||||
// do a binary search
|
||||
while li < le {
|
||||
let m = (li + le) / 2;
|
||||
if lua_getinfo(L, m, cstr!(""), &mut ar) != 0 {
|
||||
li = m + 1;
|
||||
} else {
|
||||
le = m;
|
||||
}
|
||||
}
|
||||
le - 1
|
||||
}
|
||||
|
||||
unsafe fn compat53_checkmode(
|
||||
L: *mut lua_State,
|
||||
mode: *const c_char,
|
||||
|
@ -81,7 +106,7 @@ unsafe fn compat53_checkmode(
|
|||
LUA_OK
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
unsafe fn compat53_findfield(L: *mut lua_State, objidx: c_int, level: c_int) -> c_int {
|
||||
if level == 0 || lua_istable(L, -1) == 0 {
|
||||
return 0; // not found
|
||||
|
@ -110,10 +135,18 @@ unsafe fn compat53_findfield(L: *mut lua_State, objidx: c_int, level: c_int) ->
|
|||
return 0; // not found
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
unsafe fn compat53_pushglobalfuncname(L: *mut lua_State, ar: *mut lua_Debug) -> c_int {
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
unsafe fn compat53_pushglobalfuncname(
|
||||
L: *mut lua_State,
|
||||
level: c_int,
|
||||
ar: *mut lua_Debug,
|
||||
) -> c_int {
|
||||
let top = lua_gettop(L);
|
||||
lua_getinfo(L, cstr!("f"), ar); // push function
|
||||
// push function
|
||||
#[cfg(not(feature = "luau"))]
|
||||
lua_getinfo(L, cstr!("f"), ar);
|
||||
#[cfg(feature = "luau")]
|
||||
lua_getinfo(L, level, cstr!("f"), ar);
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
if compat53_findfield(L, top + 1, 2) != 0 {
|
||||
lua_copy(L, -1, top + 1); // move name to proper place
|
||||
|
@ -125,6 +158,34 @@ unsafe fn compat53_pushglobalfuncname(L: *mut lua_State, ar: *mut lua_Debug) ->
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
unsafe fn compat53_pushfuncname(L: *mut lua_State, level: c_int, ar: *mut lua_Debug) {
|
||||
/*
|
||||
if *(*ar).namewhat != b'\0' as c_char {
|
||||
// is there a name?
|
||||
lua_pushfstring(L, cstr!("function '%s'"), (*ar).name);
|
||||
} else
|
||||
*/
|
||||
if *(*ar).what == b'm' as c_char {
|
||||
// main?
|
||||
lua_pushliteral(L, "main chunk");
|
||||
} else if *(*ar).what == b'C' as c_char {
|
||||
if compat53_pushglobalfuncname(L, level, ar) != 0 {
|
||||
lua_pushfstring(L, cstr!("function '%s'"), lua_tostring(L, -1));
|
||||
lua_remove(L, -2); // remove name
|
||||
} else {
|
||||
lua_pushliteral(L, "?");
|
||||
}
|
||||
} else {
|
||||
lua_pushfstring(
|
||||
L,
|
||||
cstr!("function <%s:%d>"),
|
||||
(*ar).short_src.as_ptr(),
|
||||
(*ar).linedefined,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) {
|
||||
if *(*ar).namewhat != b'\0' as c_char {
|
||||
|
@ -134,7 +195,7 @@ unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) {
|
|||
// main?
|
||||
lua_pushliteral(L, "main chunk");
|
||||
} else if *(*ar).what == b'C' as c_char {
|
||||
if compat53_pushglobalfuncname(L, ar) != 0 {
|
||||
if compat53_pushglobalfuncname(L, -1, ar) != 0 {
|
||||
lua_pushfstring(L, cstr!("function '%s'"), lua_tostring(L, -1));
|
||||
lua_remove(L, -2); // remove name
|
||||
} else {
|
||||
|
@ -184,22 +245,22 @@ pub unsafe fn lua_absindex(L: *mut lua_State, mut idx: c_int) -> c_int {
|
|||
}
|
||||
|
||||
// Comparison and arithmetic functions
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPADD: c_int = 0;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPSUB: c_int = 1;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPMUL: c_int = 2;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPDIV: c_int = 3;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPMOD: c_int = 4;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPPOW: c_int = 5;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPUNM: c_int = 6;
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
static COMPAT53_ARITH_CODE: &str = r#"
|
||||
local op,a,b = ...
|
||||
if op == 0 then return a+b
|
||||
|
@ -212,7 +273,7 @@ elseif op == 6 then return -a
|
|||
end
|
||||
"#;
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub unsafe fn lua_arith(L: *mut lua_State, op: c_int) {
|
||||
#[allow(clippy::manual_range_contains)]
|
||||
if op < LUA_OPADD || op > LUA_OPUNM {
|
||||
|
@ -242,7 +303,7 @@ pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int) {
|
||||
let abs_to = lua_absindex(L, toidx);
|
||||
|
@ -263,6 +324,12 @@ pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
feature = "lua52",
|
||||
feature = "lua51",
|
||||
feature = "luajit",
|
||||
feature = "luau"
|
||||
))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
|
||||
lua_tointegerx(L, i, ptr::null_mut())
|
||||
|
@ -284,6 +351,12 @@ pub unsafe fn lua_tonumberx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> l
|
|||
|
||||
// Implemented for Lua 5.2 as well
|
||||
// See https://github.com/keplerproject/lua-compat-5.3/issues/40
|
||||
#[cfg(any(
|
||||
feature = "lua52",
|
||||
feature = "lua51",
|
||||
feature = "luajit",
|
||||
feature = "luau"
|
||||
))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer {
|
||||
let mut ok = 0;
|
||||
|
@ -301,20 +374,20 @@ pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) ->
|
|||
return 0;
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize {
|
||||
lua_objlen(L, idx)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPEQ: c_int = 0;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPLT: c_int = 1;
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub const LUA_OPLE: c_int = 2;
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_compare(L: *mut lua_State, mut idx1: c_int, mut idx2: c_int, op: c_int) -> c_int {
|
||||
match op {
|
||||
|
@ -335,7 +408,7 @@ pub unsafe fn lua_compare(L: *mut lua_State, mut idx1: c_int, mut idx2: c_int, o
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char {
|
||||
if l == 0 {
|
||||
|
@ -356,7 +429,7 @@ pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) ->
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char {
|
||||
lua_pushstring_(L, s);
|
||||
|
@ -401,7 +474,7 @@ pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_in
|
|||
lua_type(L, -1)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int {
|
||||
let abs_i = lua_absindex(L, idx);
|
||||
|
@ -424,6 +497,22 @@ pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int {
|
|||
lua_type(L, -1)
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_getuservalue(L: *mut lua_State, mut idx: c_int) -> c_int {
|
||||
luaL_checkstack(L, 2, cstr!("not enough stack slots available"));
|
||||
idx = lua_absindex(L, idx);
|
||||
lua_pushliteral(L, "__mlua_uservalues");
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if lua_istable(L, -1) == 0 {
|
||||
return LUA_TNIL;
|
||||
}
|
||||
lua_pushvalue(L, idx);
|
||||
lua_rawget(L, -2);
|
||||
lua_remove(L, -2);
|
||||
lua_type(L, -1)
|
||||
}
|
||||
|
||||
#[cfg(feature = "lua52")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int {
|
||||
|
@ -449,7 +538,7 @@ pub unsafe fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer) {
|
|||
)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void) {
|
||||
let abs_i = lua_absindex(L, idx);
|
||||
|
@ -466,6 +555,34 @@ pub unsafe fn lua_setuservalue(L: *mut lua_State, idx: c_int) {
|
|||
lua_setfenv(L, idx);
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_setuservalue(L: *mut lua_State, mut idx: c_int) {
|
||||
luaL_checkstack(L, 4, cstr!("not enough stack slots available"));
|
||||
idx = lua_absindex(L, idx);
|
||||
lua_pushliteral(L, "__mlua_uservalues");
|
||||
lua_pushvalue(L, -1);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if lua_istable(L, -1) == 0 {
|
||||
lua_pop(L, 1);
|
||||
lua_createtable(L, 0, 2); // main table
|
||||
lua_createtable(L, 0, 1); // metatable
|
||||
lua_pushliteral(L, "k");
|
||||
lua_setfield(L, -2, cstr!("__mode"));
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
lua_replace(L, -2);
|
||||
lua_pushvalue(L, idx);
|
||||
lua_pushvalue(L, -3);
|
||||
lua_remove(L, -4);
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_dump(
|
||||
L: *mut lua_State,
|
||||
|
@ -476,7 +593,7 @@ pub unsafe fn lua_dump(
|
|||
lua_dump_(L, writer, data)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) {
|
||||
match lua_type(L, idx) {
|
||||
|
@ -565,7 +682,7 @@ pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void {
|
|||
return _ptr;
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
|
@ -575,7 +692,7 @@ pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
|
|||
// lauxlib ported functions
|
||||
//
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char) {
|
||||
if lua_checkstack(L, sz + LUA_MINSTACK) == 0 {
|
||||
|
@ -628,7 +745,7 @@ pub unsafe fn luaL_loadbufferx(
|
|||
luaL_loadbuffer(L, buff, sz, name)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer {
|
||||
let mut isnum = 0;
|
||||
|
@ -682,6 +799,46 @@ pub unsafe fn luaL_traceback(
|
|||
lua_concat(L, lua_gettop(L) - top);
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub unsafe fn luaL_traceback(
|
||||
L: *mut lua_State,
|
||||
L1: *mut lua_State,
|
||||
msg: *const c_char,
|
||||
mut level: c_int,
|
||||
) {
|
||||
let mut ar: lua_Debug = mem::zeroed();
|
||||
let top = lua_gettop(L);
|
||||
let numlevels = compat53_countlevels(L1);
|
||||
let mark = if numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2 {
|
||||
COMPAT53_LEVELS1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
if !msg.is_null() {
|
||||
lua_pushfstring(L, cstr!("%s\n"), msg);
|
||||
}
|
||||
lua_pushliteral(L, "stack traceback:");
|
||||
while lua_getinfo(L1, level, cstr!(""), &mut ar) != 0 {
|
||||
level += 1;
|
||||
if level == mark {
|
||||
// too many levels?
|
||||
lua_pushliteral(L, "\n\t..."); // add a '...'
|
||||
level = numlevels - COMPAT53_LEVELS2; // and skip to last ones
|
||||
} else {
|
||||
lua_getinfo(L1, level - 1, cstr!("sln"), &mut ar);
|
||||
lua_pushfstring(L, cstr!("\n\t%s:"), ar.short_src.as_ptr());
|
||||
if ar.currentline > 0 {
|
||||
lua_pushfstring(L, cstr!("%d:"), ar.currentline);
|
||||
}
|
||||
lua_pushliteral(L, " in ");
|
||||
compat53_pushfuncname(L, level - 1, &mut ar);
|
||||
lua_concat(L, lua_gettop(L) - top);
|
||||
}
|
||||
}
|
||||
lua_concat(L, lua_gettop(L) - top);
|
||||
}
|
||||
|
||||
pub unsafe fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char {
|
||||
if luaL_callmeta(L, idx, cstr!("__tostring")) == 0 {
|
||||
let t = lua_type(L, idx);
|
||||
|
@ -718,7 +875,7 @@ pub unsafe fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) ->
|
|||
lua_tolstring(L, -1, len)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) {
|
||||
luaL_checkstack(L, 1, cstr!("not enough stack slots"));
|
||||
|
@ -726,7 +883,7 @@ pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) {
|
|||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_testudata(L: *mut lua_State, i: c_int, tname: *const c_char) -> *mut c_void {
|
||||
let mut p = lua_touserdata(L, i);
|
||||
|
@ -762,7 +919,7 @@ pub unsafe fn luaL_setfuncs(L: *mut lua_State, mut l: *const luaL_Reg, nup: c_in
|
|||
lua_pop(L, nup); // remove upvalues
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
pub unsafe fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int {
|
||||
let abs_i = lua_absindex(L, idx);
|
||||
luaL_checkstack(L, 3, cstr!("not enough stack slots"));
|
||||
|
@ -791,7 +948,7 @@ pub unsafe fn luaL_requiref(
|
|||
lua_pop(L, 1);
|
||||
lua_pushcfunction(L, openf);
|
||||
lua_pushstring(L, modname);
|
||||
#[cfg(any(feature = "lua52", feature = "lua51"))]
|
||||
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luau"))]
|
||||
{
|
||||
lua_call(L, 1, 1);
|
||||
lua_pushvalue(L, -1);
|
||||
|
@ -803,7 +960,7 @@ pub unsafe fn luaL_requiref(
|
|||
lua_getfield(L, -1, modname);
|
||||
}
|
||||
}
|
||||
if cfg!(any(feature = "lua52", feature = "lua51")) && glb != 0 {
|
||||
if cfg!(any(feature = "lua52", feature = "lua51", feature = "luau")) && glb != 0 {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, modname);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ pub use super::lua52::lauxlib::*;
|
|||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
pub use super::lua51::lauxlib::*;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub use super::luau::lauxlib::*;
|
||||
|
||||
#[cfg(feature = "lua52")]
|
||||
pub use super::compat53::{luaL_getmetafield, luaL_newmetatable, luaL_requiref, luaL_tolstring};
|
||||
|
||||
|
@ -24,6 +27,12 @@ pub use super::compat53::{
|
|||
luaL_tolstring, luaL_traceback,
|
||||
};
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub use super::compat53::{
|
||||
luaL_checkstack, luaL_getmetafield, luaL_getsubtable, luaL_len, luaL_newmetatable,
|
||||
luaL_requiref, luaL_setmetatable, luaL_testudata, luaL_tolstring, luaL_traceback,
|
||||
};
|
||||
|
||||
// I believe `luaL_traceback` < 5.4 requires this much free stack to not error.
|
||||
// 5.4 uses `luaL_Buffer`
|
||||
pub const LUA_TRACEBACK_STACK: c_int = 11;
|
||||
|
|
|
@ -14,6 +14,9 @@ pub use super::lua52::lua::*;
|
|||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
pub use super::lua51::lua::*;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub use super::luau::lua::*;
|
||||
|
||||
#[cfg(feature = "lua52")]
|
||||
pub use super::compat53::{
|
||||
lua_dump, lua_getextraspace, lua_getfield, lua_getglobal, lua_geti, lua_gettable,
|
||||
|
@ -31,6 +34,14 @@ pub use super::compat53::{
|
|||
lua_stringtonumber, lua_tointeger, lua_tointegerx, lua_tonumberx,
|
||||
};
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub use super::compat53::{
|
||||
lua_arith, lua_compare, lua_copy, lua_getextraspace, lua_getfield, lua_getglobal, lua_geti,
|
||||
lua_gettable, lua_getuservalue, lua_isinteger, lua_len, lua_pushglobaltable, lua_pushlstring,
|
||||
lua_pushstring, lua_rawget, lua_rawgeti, lua_rawgetp, lua_rawlen, lua_rawseti, lua_rawsetp,
|
||||
lua_rotate, lua_seti, lua_setuservalue, lua_stringtonumber, lua_tointeger, lua_tointegerx,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "lua52", feature = "lua53", feature = "lua54",))]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 255;
|
||||
|
||||
|
@ -40,6 +51,9 @@ pub const LUA_MAX_UPVALUES: c_int = 60;
|
|||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 120;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub const LUA_MAX_UPVALUES: c_int = 200;
|
||||
|
||||
//
|
||||
// Lua 5.4 compatibility layer
|
||||
//
|
||||
|
@ -48,7 +62,8 @@ pub const LUA_MAX_UPVALUES: c_int = 120;
|
|||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "lua51",
|
||||
feature = "luajit"
|
||||
feature = "luajit",
|
||||
feature = "luau"
|
||||
))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_resume(
|
||||
|
@ -62,22 +77,32 @@ pub unsafe fn lua_resume(
|
|||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
let ret = lua_resume_(L, narg);
|
||||
|
||||
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luau"))]
|
||||
let ret = lua_resume_(L, from, narg);
|
||||
|
||||
if ret == LUA_OK || ret == LUA_YIELD {
|
||||
if (ret == LUA_OK || ret == LUA_YIELD) && !(nres.is_null()) {
|
||||
*nres = lua_gettop(L);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua54", all(feature = "luajit", feature = "vendored")))]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "luau",
|
||||
all(feature = "luajit", feature = "vendored")
|
||||
))]
|
||||
pub unsafe fn lua_resetthreadx(L: *mut lua_State, th: *mut lua_State) -> c_int {
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
{
|
||||
lua_resetthread(L, th);
|
||||
LUA_OK
|
||||
}
|
||||
#[cfg(feature = "luau")]
|
||||
{
|
||||
let _ = L;
|
||||
lua_resetthread(th);
|
||||
LUA_OK
|
||||
}
|
||||
#[cfg(feature = "lua54")]
|
||||
{
|
||||
let _ = L;
|
||||
|
|
|
@ -11,3 +11,6 @@ pub use super::lua52::lualib::*;
|
|||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
pub use super::lua51::lualib::*;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub use super::luau::lualib::*;
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
//! Contains definitions from `lualib.h`.
|
||||
|
||||
use std::alloc;
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::{c_char, c_float, c_int, c_void};
|
||||
use std::ptr;
|
||||
|
||||
use super::lua::{
|
||||
self, lua_CFunction, lua_Integer, lua_Number, lua_State, lua_Unsigned, LUA_ERRSYNTAX, LUA_OK,
|
||||
LUA_REGISTRYINDEX,
|
||||
};
|
||||
use super::luacode;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct luaL_Reg {
|
||||
pub name: *const c_char,
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn luaL_register(L: *mut lua_State, libname: *const c_char, l: *const luaL_Reg);
|
||||
#[link_name = "luaL_getmetafield"]
|
||||
pub fn luaL_getmetafield_(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
pub fn luaL_callmeta(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
#[link_name = "luaL_typeerrorL"]
|
||||
pub fn luaL_typeerror(L: *mut lua_State, narg: c_int, tname: *const c_char) -> !;
|
||||
#[link_name = "luaL_argerrorL"]
|
||||
pub fn luaL_argerror(L: *mut lua_State, narg: c_int, extramsg: *const c_char) -> !;
|
||||
pub fn luaL_checklstring(L: *mut lua_State, narg: c_int, l: *mut usize) -> *const c_char;
|
||||
pub fn luaL_optlstring(
|
||||
L: *mut lua_State,
|
||||
narg: c_int,
|
||||
def: *const c_char,
|
||||
l: *mut usize,
|
||||
) -> *const c_char;
|
||||
pub fn luaL_checknumber(L: *mut lua_State, narg: c_int) -> lua_Number;
|
||||
pub fn luaL_optnumber(L: *mut lua_State, narg: c_int, def: lua_Number) -> lua_Number;
|
||||
|
||||
pub fn luaL_checkboolean(L: *mut lua_State, narg: c_int) -> c_int;
|
||||
pub fn luaL_optboolean(L: *mut lua_State, narg: c_int, def: c_int) -> c_int;
|
||||
|
||||
pub fn luaL_checkinteger(L: *mut lua_State, narg: c_int) -> lua_Integer;
|
||||
pub fn luaL_optinteger(L: *mut lua_State, narg: c_int, def: lua_Integer) -> lua_Integer;
|
||||
pub fn luaL_checkunsigned(L: *mut lua_State, narg: c_int) -> lua_Unsigned;
|
||||
pub fn luaL_optunsigned(L: *mut lua_State, narg: c_int, def: lua_Unsigned) -> lua_Unsigned;
|
||||
|
||||
pub fn luaL_checkvector(L: *mut lua_State, narg: c_int) -> *const c_float;
|
||||
pub fn luaL_optvector(L: *mut lua_State, narg: c_int, def: *const c_float) -> *const c_float;
|
||||
|
||||
#[link_name = "luaL_checkstack"]
|
||||
pub fn luaL_checkstack_(L: *mut lua_State, sz: c_int, msg: *const c_char);
|
||||
pub fn luaL_checktype(L: *mut lua_State, narg: c_int, t: c_int);
|
||||
pub fn luaL_checkany(L: *mut lua_State, narg: c_int);
|
||||
|
||||
#[link_name = "luaL_newmetatable"]
|
||||
pub fn luaL_newmetatable_(L: *mut lua_State, tname: *const c_char) -> c_int;
|
||||
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
|
||||
|
||||
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
|
||||
|
||||
#[link_name = "luaL_errorL"]
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
|
||||
|
||||
pub fn luaL_checkoption(
|
||||
L: *mut lua_State,
|
||||
narg: c_int,
|
||||
def: *const c_char,
|
||||
lst: *const *const c_char,
|
||||
) -> c_int;
|
||||
|
||||
#[link_name = "luaL_tolstring"]
|
||||
pub fn luaL_tolstring_(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
|
||||
|
||||
pub fn luaL_newstate() -> *mut lua_State;
|
||||
|
||||
// TODO: luaL_findtable
|
||||
}
|
||||
|
||||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_argcheck(L: *mut lua_State, cond: c_int, arg: c_int, extramsg: *const c_char) {
|
||||
if cond == 0 {
|
||||
luaL_argerror(L, arg, extramsg);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_argexpected(L: *mut lua_State, cond: c_int, arg: c_int, tname: *const c_char) {
|
||||
if cond == 0 {
|
||||
luaL_typeerror(L, arg, tname);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_checkstring(L: *mut lua_State, n: c_int) -> *const c_char {
|
||||
luaL_checklstring(L, n, ptr::null_mut())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_optstring(L: *mut lua_State, n: c_int, d: *const c_char) -> *const c_char {
|
||||
luaL_optlstring(L, n, d, ptr::null_mut())
|
||||
}
|
||||
|
||||
// TODO: luaL_opt
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_typename(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||
lua::lua_typename(L, lua::lua_type(L, i))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) {
|
||||
lua::lua_getfield_(L, LUA_REGISTRYINDEX, n);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int {
|
||||
assert_eq!(t, LUA_REGISTRYINDEX);
|
||||
let r = lua::lua_ref(L, -1);
|
||||
lua::lua_pop(L, 1);
|
||||
r
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int) {
|
||||
assert_eq!(t, LUA_REGISTRYINDEX);
|
||||
lua::lua_unref(L, r#ref)
|
||||
}
|
||||
|
||||
pub unsafe fn luaL_loadbufferx(
|
||||
L: *mut lua_State,
|
||||
data: *const c_char,
|
||||
mut size: usize,
|
||||
name: *const c_char,
|
||||
mode: *const c_char,
|
||||
) -> c_int {
|
||||
let chunk_is_text = (*data as u8) >= b'\n';
|
||||
if !mode.is_null() {
|
||||
let modeb = CStr::from_ptr(mode).to_bytes();
|
||||
if !chunk_is_text && !modeb.contains(&b'b') {
|
||||
lua::lua_pushfstring(
|
||||
L,
|
||||
cstr!("attempt to load a binary chunk (mode is '%s')"),
|
||||
mode,
|
||||
);
|
||||
return LUA_ERRSYNTAX;
|
||||
} else if chunk_is_text && !modeb.contains(&b't') {
|
||||
lua::lua_pushfstring(
|
||||
L,
|
||||
cstr!("attempt to load a text chunk (mode is '%s')"),
|
||||
mode,
|
||||
);
|
||||
return LUA_ERRSYNTAX;
|
||||
}
|
||||
}
|
||||
|
||||
if chunk_is_text {
|
||||
let data = luacode::luau_compile(data, size, ptr::null_mut(), &mut size);
|
||||
let layout = alloc::Layout::from_size_align_unchecked(size, super::super::SYS_MIN_ALIGN);
|
||||
let ok = lua::luau_load(L, name, data, size, 0) == 0;
|
||||
alloc::dealloc(data as *mut u8, layout);
|
||||
if !ok {
|
||||
return LUA_ERRSYNTAX;
|
||||
}
|
||||
} else {
|
||||
if lua::luau_load(L, name, data, size, 0) != 0 {
|
||||
return LUA_ERRSYNTAX;
|
||||
}
|
||||
}
|
||||
LUA_OK
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_loadbuffer(
|
||||
L: *mut lua_State,
|
||||
data: *const c_char,
|
||||
size: usize,
|
||||
name: *const c_char,
|
||||
) -> c_int {
|
||||
luaL_loadbufferx(L, data, size, name, ptr::null())
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Generic Buffer Manipulation
|
||||
//
|
|
@ -69,6 +69,9 @@ pub type lua_Unsigned = c_uint;
|
|||
pub type lua_CFunction = unsafe extern "C" fn(L: *mut lua_State) -> c_int;
|
||||
pub type lua_Continuation = unsafe extern "C" fn(L: *mut lua_State, status: c_int) -> c_int;
|
||||
|
||||
/// Type for userdata destructor functions.
|
||||
pub type lua_Udestructor = unsafe extern "C" fn(*mut c_void);
|
||||
|
||||
/// Type for memory-allocation functions.
|
||||
pub type lua_Alloc = unsafe extern "C" fn(
|
||||
L: *mut lua_State,
|
||||
|
@ -121,14 +124,15 @@ extern "C" {
|
|||
pub fn lua_lessthan(L: *mut lua_State, idx1: c_int, idx2: c_int) -> c_int;
|
||||
|
||||
pub fn lua_tonumberx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Number;
|
||||
pub fn lua_tointegerx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Integer;
|
||||
#[link_name = "lua_tointegerx"]
|
||||
pub fn lua_tointegerx_(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Integer;
|
||||
pub fn lua_tounsignedx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Unsigned;
|
||||
pub fn lua_tovector(L: *mut lua_State, idx: c_int) -> *const c_float;
|
||||
pub fn lua_toboolean(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
|
||||
pub fn lua_tostringatom(L: *mut lua_State, idx: c_int, atom: *mut c_int) -> *const c_char;
|
||||
pub fn lua_namecallatom(L: *mut lua_State, atom: *mut c_int) -> *const c_char;
|
||||
pub fn lua_objlen(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_objlen(L: *mut lua_State, idx: c_int) -> usize;
|
||||
pub fn lua_tocfunction(L: *mut lua_State, idx: c_int) -> Option<lua_CFunction>;
|
||||
pub fn lua_touserdata(L: *mut lua_State, idx: c_int) -> *mut c_void;
|
||||
pub fn lua_touserdatatagged(L: *mut lua_State, idx: c_int, tag: c_int) -> *mut c_void;
|
||||
|
@ -144,8 +148,10 @@ extern "C" {
|
|||
pub fn lua_pushinteger(L: *mut lua_State, n: lua_Integer);
|
||||
pub fn lua_pushunsigned(L: *mut lua_State, n: lua_Unsigned);
|
||||
pub fn lua_pushvector(L: *mut lua_State, x: c_float, y: c_float, z: c_float);
|
||||
pub fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize);
|
||||
pub fn lua_pushstring(L: *mut lua_State, s: *const c_char);
|
||||
#[link_name = "lua_pushlstring"]
|
||||
pub fn lua_pushlstring_(L: *mut lua_State, s: *const c_char, l: usize);
|
||||
#[link_name = "lua_pushstring"]
|
||||
pub fn lua_pushstring_(L: *mut lua_State, s: *const c_char);
|
||||
// lua_pushvfstring
|
||||
#[link_name = "lua_pushfstringL"]
|
||||
pub fn lua_pushfstring(L: *mut lua_State, fmt: *const c_char, ...) -> *const c_char;
|
||||
|
@ -163,11 +169,15 @@ extern "C" {
|
|||
//
|
||||
// Get functions (Lua -> stack)
|
||||
//
|
||||
pub fn lua_gettable(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char);
|
||||
#[link_name = "lua_gettable"]
|
||||
pub fn lua_gettable_(L: *mut lua_State, idx: c_int);
|
||||
#[link_name = "lua_getfield"]
|
||||
pub fn lua_getfield_(L: *mut lua_State, idx: c_int, k: *const c_char);
|
||||
pub fn lua_rawgetfield(L: *mut lua_State, idx: c_int, k: *const c_char);
|
||||
pub fn lua_rawget(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: c_int);
|
||||
#[link_name = "lua_rawget"]
|
||||
pub fn lua_rawget_(L: *mut lua_State, idx: c_int);
|
||||
#[link_name = "lua_rawgeti"]
|
||||
pub fn lua_rawgeti_(L: *mut lua_State, idx: c_int, n: c_int);
|
||||
pub fn lua_createtable(L: *mut lua_State, narr: c_int, nrec: c_int);
|
||||
|
||||
pub fn lua_setreadonly(L: *mut lua_State, idx: c_int, enabled: c_int);
|
||||
|
@ -175,7 +185,7 @@ extern "C" {
|
|||
pub fn lua_setsafeenv(L: *mut lua_State, idx: c_int, enabled: c_int);
|
||||
|
||||
pub fn lua_newuserdatatagged(L: *mut lua_State, sz: usize, tag: c_int) -> *mut c_void;
|
||||
pub fn lua_newuserdatadtor(L: *mut lua_State, sz: usize, dtor: fn(*mut c_void));
|
||||
pub fn lua_newuserdatadtor(L: *mut lua_State, sz: usize, dtor: lua_Udestructor) -> *mut c_void;
|
||||
pub fn lua_getmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
|
||||
pub fn lua_getfenv(L: *mut lua_State, idx: c_int);
|
||||
|
||||
|
@ -185,7 +195,8 @@ extern "C" {
|
|||
pub fn lua_settable(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_setfield(L: *mut lua_State, idx: c_int, k: *const c_char);
|
||||
pub fn lua_rawset(L: *mut lua_State, idx: c_int);
|
||||
pub fn lua_rawseti(L: *mut lua_State, idx: c_int, n: c_int);
|
||||
#[link_name = "lua_rawseti"]
|
||||
pub fn lua_rawseti_(L: *mut lua_State, idx: c_int, n: c_int);
|
||||
pub fn lua_setmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
|
||||
pub fn lua_setfenv(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
|
||||
|
@ -207,7 +218,8 @@ extern "C" {
|
|||
//
|
||||
pub fn lua_yield(L: *mut lua_State, nresults: c_int) -> c_int;
|
||||
pub fn lua_break(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_resume(L: *mut lua_State, from: *mut lua_State, narg: c_int) -> c_int;
|
||||
#[link_name = "lua_resume"]
|
||||
pub fn lua_resume_(L: *mut lua_State, from: *mut lua_State, narg: c_int) -> c_int;
|
||||
pub fn lua_resumeerror(L: *mut lua_State, from: *mut lua_State) -> c_int;
|
||||
pub fn lua_status(L: *mut lua_State) -> c_int;
|
||||
pub fn lua_isyieldable(L: *mut lua_State) -> c_int;
|
||||
|
@ -241,7 +253,7 @@ extern "C" {
|
|||
pub fn lua_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||
// TODO: lua_encodepointer, lua_clock
|
||||
pub fn lua_setuserdatadtor(L: *mut lua_State, tag: c_int, dtor: fn(*mut c_void));
|
||||
pub fn lua_setuserdatadtor(L: *mut lua_State, tag: c_int, dtor: Option<lua_Udestructor>);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -258,14 +270,15 @@ extern "C" {
|
|||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number {
|
||||
lua_tonumberx(L, i, ptr::null_mut())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
|
||||
lua_tointegerx(L, i, ptr::null_mut())
|
||||
pub unsafe fn lua_tointeger_(L: *mut lua_State, i: c_int) -> lua_Integer {
|
||||
lua_tointegerx_(L, i, ptr::null_mut())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -339,14 +352,22 @@ pub unsafe fn lua_isnoneornil(L: *mut lua_State, n: c_int) -> c_int {
|
|||
pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &'static str) {
|
||||
use std::ffi::CString;
|
||||
let c_str = CString::new(s).unwrap();
|
||||
lua_pushlstring(L, c_str.as_ptr(), c_str.as_bytes().len())
|
||||
lua_pushlstring_(L, c_str.as_ptr(), c_str.as_bytes().len())
|
||||
}
|
||||
|
||||
pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction, debugname: *const c_char) {
|
||||
pub unsafe fn lua_pushcfunction(L: *mut lua_State, f: lua_CFunction) {
|
||||
lua_pushcclosurek(L, f, ptr::null(), 0, None)
|
||||
}
|
||||
|
||||
pub unsafe fn lua_pushcfunctiond(L: *mut lua_State, f: lua_CFunction, debugname: *const c_char) {
|
||||
lua_pushcclosurek(L, f, debugname, 0, None)
|
||||
}
|
||||
|
||||
pub unsafe fn lua_pushcclosure(
|
||||
pub unsafe fn lua_pushcclosure(L: *mut lua_State, f: lua_CFunction, nup: c_int) {
|
||||
lua_pushcclosurek(L, f, ptr::null(), nup, None)
|
||||
}
|
||||
|
||||
pub unsafe fn lua_pushcclosured(
|
||||
L: *mut lua_State,
|
||||
f: lua_CFunction,
|
||||
debugname: *const c_char,
|
||||
|
@ -361,8 +382,8 @@ pub unsafe fn lua_setglobal(L: *mut lua_State, var: *const c_char) {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn lua_getglobal(L: *mut lua_State, var: *const c_char) {
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, var)
|
||||
pub unsafe fn lua_getglobal_(L: *mut lua_State, var: *const c_char) {
|
||||
lua_getfield_(L, LUA_GLOBALSINDEX, var)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
//! Contains definitions from `luacode.h`.
|
||||
|
||||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct lua_CompileOptions {
|
||||
pub optimizationLevel: c_int,
|
||||
pub debugLevel: c_int,
|
||||
pub coverageLevel: c_int,
|
||||
pub vectorLib: *const c_char,
|
||||
pub vectorCtor: *const c_char,
|
||||
pub mutableGlobals: *mut *const c_char,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn luau_compile(
|
||||
source: *const c_char,
|
||||
size: usize,
|
||||
options: *mut lua_CompileOptions,
|
||||
outsize: *mut usize,
|
||||
) -> *mut c_char;
|
||||
}
|
|
@ -1,88 +1,8 @@
|
|||
//! Contains definitions from `lualib.h`.
|
||||
|
||||
use std::os::raw::{c_char, c_float, c_int, c_void};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
use super::lua::{
|
||||
lua_CFunction, lua_Integer, lua_Number, lua_State, lua_Unsigned, lua_getfield,
|
||||
LUA_REGISTRYINDEX,
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct luaL_Reg {
|
||||
pub name: *const c_char,
|
||||
pub func: lua_CFunction,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn luaL_register(L: *mut lua_State, libname: *const c_char, l: *const luaL_Reg);
|
||||
pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
pub fn luaL_callmeta(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
|
||||
// TODO: luaL_typeerrorL, luaL_argerrorL
|
||||
pub fn luaL_checklstring(L: *mut lua_State, narg: c_int, l: *mut usize) -> *const c_char;
|
||||
pub fn luaL_optlstring(
|
||||
L: *mut lua_State,
|
||||
narg: c_int,
|
||||
def: *const c_char,
|
||||
l: *mut usize,
|
||||
) -> *const c_char;
|
||||
pub fn luaL_checknumber(L: *mut lua_State, narg: c_int) -> lua_Number;
|
||||
pub fn luaL_optnumber(L: *mut lua_State, narg: c_int, def: lua_Number) -> lua_Number;
|
||||
|
||||
pub fn luaL_checkboolean(L: *mut lua_State, narg: c_int) -> c_int;
|
||||
pub fn luaL_optboolean(L: *mut lua_State, narg: c_int, def: c_int) -> c_int;
|
||||
|
||||
pub fn luaL_checkinteger(L: *mut lua_State, narg: c_int) -> lua_Integer;
|
||||
pub fn luaL_optinteger(L: *mut lua_State, narg: c_int, def: lua_Integer) -> lua_Integer;
|
||||
pub fn luaL_checkunsigned(L: *mut lua_State, narg: c_int) -> lua_Unsigned;
|
||||
pub fn luaL_optunsigned(L: *mut lua_State, narg: c_int, def: lua_Unsigned) -> lua_Unsigned;
|
||||
|
||||
pub fn luaL_checkvector(L: *mut lua_State, narg: c_int) -> *const c_float;
|
||||
pub fn luaL_optvector(L: *mut lua_State, narg: c_int, def: *const c_float) -> *const c_float;
|
||||
|
||||
pub fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char);
|
||||
pub fn luaL_checktype(L: *mut lua_State, narg: c_int, t: c_int);
|
||||
pub fn luaL_checkany(L: *mut lua_State, narg: c_int);
|
||||
|
||||
pub fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int;
|
||||
pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
|
||||
|
||||
pub fn luaL_where(L: *mut lua_State, lvl: c_int);
|
||||
|
||||
#[link_name = "luaL_errorL"]
|
||||
pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> !;
|
||||
|
||||
pub fn luaL_checkoption(
|
||||
L: *mut lua_State,
|
||||
narg: c_int,
|
||||
def: *const c_char,
|
||||
lst: *const *const c_char,
|
||||
) -> c_int;
|
||||
|
||||
pub fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut usize) -> *const c_char;
|
||||
|
||||
pub fn luaL_newstate() -> *mut lua_State;
|
||||
|
||||
// TODO: luaL_findtable
|
||||
}
|
||||
|
||||
//
|
||||
// Some useful macros (implemented as Rust functions)
|
||||
//
|
||||
|
||||
// TODO: luaL_argcheck, luaL_argexpected, luaL_checkstring, luaL_optstring, luaL_typename, luaL_opt
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, n);
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Generic Buffer Manipulation
|
||||
//
|
||||
|
||||
//
|
||||
// Builtin libraries
|
||||
//
|
||||
use super::lua::lua_State;
|
||||
|
||||
pub const LUA_COLIBNAME: &str = "coroutine";
|
||||
pub const LUA_TABLIBNAME: &str = "table";
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
//! Low level bindings to Luau.
|
||||
|
||||
pub use self::lauxlib::*;
|
||||
pub use self::lua::*;
|
||||
pub use self::luacode::*;
|
||||
pub use self::lualib::*;
|
||||
|
||||
pub mod lauxlib;
|
||||
pub mod lua;
|
||||
pub mod luacode;
|
||||
pub mod lualib;
|
||||
|
|
|
@ -42,6 +42,7 @@ pub const SYS_MIN_ALIGN: usize = 4;
|
|||
|
||||
// Hack to avoid stripping a few unused Lua symbols that could be imported
|
||||
// by C modules in unsafe mode
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub(crate) fn keep_lua_symbols() {
|
||||
let mut symbols: Vec<*const extern "C" fn()> = Vec::new();
|
||||
symbols.push(lua_atpanic as _);
|
||||
|
@ -59,14 +60,25 @@ mod lauxlib;
|
|||
mod lua;
|
||||
mod lualib;
|
||||
|
||||
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(
|
||||
feature = "lua52",
|
||||
feature = "lua51",
|
||||
feature = "luajit",
|
||||
feature = "luau"
|
||||
))]
|
||||
mod compat53;
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
pub mod lua54;
|
||||
|
||||
#[cfg(feature = "lua53")]
|
||||
pub mod lua53;
|
||||
|
||||
#[cfg(feature = "lua52")]
|
||||
pub mod lua52;
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
pub mod lua51;
|
||||
#[cfg(feature = "lua52")]
|
||||
pub mod lua52;
|
||||
#[cfg(feature = "lua53")]
|
||||
pub mod lua53;
|
||||
#[cfg(feature = "lua54")]
|
||||
pub mod lua54;
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
pub mod luau;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::os::raw::{c_int, c_void};
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
|
@ -214,7 +213,11 @@ impl<'lua> Function<'lua> {
|
|||
///
|
||||
/// If `strip` is true, the binary representation may not include all debug information
|
||||
/// about the function, to save space.
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub fn dump(&self, strip: bool) -> Vec<u8> {
|
||||
use std::os::raw::c_void;
|
||||
use std::slice;
|
||||
|
||||
unsafe extern "C" fn writer(
|
||||
_state: *mut ffi::lua_State,
|
||||
buf: *const c_void,
|
||||
|
|
|
@ -85,6 +85,7 @@ mod conversion;
|
|||
mod error;
|
||||
mod ffi;
|
||||
mod function;
|
||||
#[cfg(not(feature = "luau"))]
|
||||
mod hook;
|
||||
mod lua;
|
||||
mod multi;
|
||||
|
@ -104,6 +105,7 @@ pub use crate::{ffi::lua_CFunction, ffi::lua_State};
|
|||
|
||||
pub use crate::error::{Error, ExternalError, ExternalResult, Result};
|
||||
pub use crate::function::Function;
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack, HookTriggers};
|
||||
pub use crate::lua::{AsChunk, Chunk, ChunkMode, GCMode, Lua, LuaOptions};
|
||||
pub use crate::multi::Variadic;
|
||||
|
|
119
src/lua.rs
119
src/lua.rs
|
@ -14,6 +14,7 @@ use rustc_hash::FxHashMap;
|
|||
use crate::error::{Error, Result};
|
||||
use crate::ffi;
|
||||
use crate::function::Function;
|
||||
#[cfg(not(feature = "luau"))]
|
||||
use crate::hook::{Debug, HookTriggers};
|
||||
use crate::scope::Scope;
|
||||
use crate::stdlib::StdLib;
|
||||
|
@ -21,8 +22,8 @@ use crate::string::String;
|
|||
use crate::table::Table;
|
||||
use crate::thread::Thread;
|
||||
use crate::types::{
|
||||
Callback, CallbackUpvalue, DestructedUserdataMT, HookCallback, Integer, LightUserData, LuaRef,
|
||||
MaybeSend, Number, RegistryKey,
|
||||
Callback, CallbackUpvalue, DestructedUserdataMT, /*HookCallback,*/ Integer, LightUserData,
|
||||
LuaRef, MaybeSend, Number, RegistryKey,
|
||||
};
|
||||
use crate::userdata::{
|
||||
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
||||
|
@ -35,6 +36,9 @@ use crate::util::{
|
|||
};
|
||||
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
use crate::types::HookCallback;
|
||||
|
||||
#[cfg(not(feature = "lua54"))]
|
||||
use crate::util::push_userdata;
|
||||
#[cfg(feature = "lua54")]
|
||||
|
@ -103,6 +107,7 @@ struct ExtraData {
|
|||
#[cfg(feature = "async")]
|
||||
ref_waker_idx: c_int,
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
hook_callback: Option<HookCallback>,
|
||||
#[cfg(feature = "lua54")]
|
||||
warn_callback: Option<WarnCallback>,
|
||||
|
@ -310,6 +315,7 @@ impl Lua {
|
|||
|
||||
let mut lua = unsafe { Self::inner_new(libs, options) };
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
if libs.contains(StdLib::PACKAGE) {
|
||||
mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
|
||||
}
|
||||
|
@ -328,12 +334,16 @@ impl Lua {
|
|||
///
|
||||
/// [`StdLib`]: crate::StdLib
|
||||
pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
ffi::keep_lua_symbols();
|
||||
Self::inner_new(libs, options)
|
||||
}
|
||||
|
||||
unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
|
||||
#[cfg_attr(any(feature = "lua51", feature = "luajit"), allow(dead_code))]
|
||||
#[cfg_attr(
|
||||
any(feature = "lua51", feature = "luajit", feature = "luau"),
|
||||
allow(dead_code)
|
||||
)]
|
||||
unsafe extern "C" fn allocator(
|
||||
extra_data: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
|
@ -398,9 +408,14 @@ impl Lua {
|
|||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
let state = ffi::lua_newstate(allocator, mem_info as *mut c_void);
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
let state = ffi::luaL_newstate();
|
||||
|
||||
// #[cfg(feature = "luau")]
|
||||
// {
|
||||
// ffi::luaL_sandbox(state);
|
||||
// }
|
||||
|
||||
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
|
||||
ffi::lua_pop(state, 1);
|
||||
|
||||
|
@ -427,7 +442,7 @@ impl Lua {
|
|||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
ffi::lua_rawgeti(lua.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
ffi::lua_pushvalue(lua.state, ffi::LUA_GLOBALSINDEX);
|
||||
|
||||
ffi::lua_pushcfunction(lua.state, safe_pcall);
|
||||
|
@ -447,6 +462,9 @@ impl Lua {
|
|||
extra.recycled_thread_cache = Vec::with_capacity(options.thread_cache_size);
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
mlua_expect!(lua.prepare_luau_state(), "Error preparing Luau state");
|
||||
|
||||
lua
|
||||
}
|
||||
|
||||
|
@ -534,6 +552,7 @@ impl Lua {
|
|||
recycled_thread_cache: Vec::new(),
|
||||
#[cfg(feature = "async")]
|
||||
ref_waker_idx,
|
||||
#[cfg(not(feature = "luau"))]
|
||||
hook_callback: None,
|
||||
#[cfg(feature = "lua54")]
|
||||
warn_callback: None,
|
||||
|
@ -600,10 +619,13 @@ impl Lua {
|
|||
|
||||
// If `package` library loaded into a safe lua state then disable C modules
|
||||
let extra = unsafe { &mut *self.extra.get() };
|
||||
#[cfg(not(feature = "luau"))]
|
||||
{
|
||||
let curr_libs = extra.libs;
|
||||
if self.safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) {
|
||||
mlua_expect!(self.disable_c_modules(), "Error during disabling C modules");
|
||||
}
|
||||
}
|
||||
extra.libs |= libs;
|
||||
|
||||
res
|
||||
|
@ -795,6 +817,7 @@ impl Lua {
|
|||
///
|
||||
/// [`HookTriggers`]: crate::HookTriggers
|
||||
/// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
|
||||
where
|
||||
F: 'static + MaybeSend + FnMut(&Lua, Debug) -> Result<()>,
|
||||
|
@ -832,6 +855,7 @@ impl Lua {
|
|||
|
||||
/// Remove any hook previously set by `set_hook`. This function has no effect if a hook was not
|
||||
/// previously set.
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub fn remove_hook(&self) {
|
||||
// If main_state is not available, then sethook wasn't called.
|
||||
let state = match self.main_state {
|
||||
|
@ -909,6 +933,7 @@ impl Lua {
|
|||
/// function that has called level `n` (except for tail calls, which do not count in the stack).
|
||||
///
|
||||
/// [`Debug`]: crate::hook::Debug
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
|
||||
unsafe {
|
||||
let mut ar: ffi::lua_Debug = mem::zeroed();
|
||||
|
@ -961,7 +986,12 @@ impl Lua {
|
|||
/// Returns true if the garbage collector is currently running automatically.
|
||||
///
|
||||
/// Requires `feature = "lua54/lua53/lua52"`
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "luau"
|
||||
))]
|
||||
pub fn gc_is_running(&self) -> bool {
|
||||
let state = self.main_state.unwrap_or(self.state);
|
||||
unsafe { ffi::lua_gc(state, ffi::LUA_GCISRUNNING, 0) != 0 }
|
||||
|
@ -1018,6 +1048,7 @@ impl Lua {
|
|||
/// [documentation][lua_doc].
|
||||
///
|
||||
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub fn gc_set_pause(&self, pause: c_int) -> c_int {
|
||||
let state = self.main_state.unwrap_or(self.state);
|
||||
unsafe { ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, pause) }
|
||||
|
@ -1040,6 +1071,7 @@ impl Lua {
|
|||
/// More information can be found in the Lua [documentation][lua_doc].
|
||||
///
|
||||
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5.1
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub fn gc_inc(&self, pause: c_int, step_multiplier: c_int, step_size: c_int) -> GCMode {
|
||||
let state = self.main_state.unwrap_or(self.state);
|
||||
|
||||
|
@ -1138,6 +1170,7 @@ impl Lua {
|
|||
}
|
||||
Some(ChunkMode::Binary) => cstr!("b"),
|
||||
Some(ChunkMode::Text) => cstr!("t"),
|
||||
#[cfg(not(feature = "luau"))]
|
||||
None if source.starts_with(ffi::LUA_SIGNATURE) && self.safe => {
|
||||
return Err(Error::SafetyError(
|
||||
"binary chunks are disabled in safe mode".to_string(),
|
||||
|
@ -1158,7 +1191,7 @@ impl Lua {
|
|||
self.push_value(env)?;
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
ffi::lua_setupvalue(self.state, -2, 1);
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
ffi::lua_setfenv(self.state, -2);
|
||||
}
|
||||
Ok(Function(self.pop_ref()))
|
||||
|
@ -1488,7 +1521,7 @@ impl Lua {
|
|||
assert_stack(self.state, 1);
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX);
|
||||
Table(self.pop_ref())
|
||||
}
|
||||
|
@ -2329,7 +2362,12 @@ impl Lua {
|
|||
where
|
||||
'lua: 'callback,
|
||||
{
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "luau"
|
||||
))]
|
||||
unsafe {
|
||||
let libs = (*self.extra.get()).libs;
|
||||
if !libs.contains(StdLib::COROUTINE) {
|
||||
|
@ -2551,6 +2589,7 @@ impl Lua {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
fn disable_c_modules(&self) -> Result<()> {
|
||||
let package: Table = self.globals().get("package")?;
|
||||
|
||||
|
@ -2577,6 +2616,42 @@ impl Lua {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
unsafe fn prepare_luau_state(&self) -> Result<()> {
|
||||
use std::ffi::CStr;
|
||||
|
||||
// Since Luau has some missing standard function, we re-implement them here
|
||||
// They are: collectgarbage, loadstring, require
|
||||
|
||||
unsafe extern "C" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_int {
|
||||
let option = ffi::luaL_optstring(state, 1, cstr!("collect"));
|
||||
let option = CStr::from_ptr(option);
|
||||
match option.to_str() {
|
||||
Ok("collect") => {
|
||||
ffi::lua_gc(state, ffi::LUA_GCCOLLECT, 0);
|
||||
return 0;
|
||||
}
|
||||
Ok("count") => {
|
||||
let n = ffi::lua_gc(state, ffi::LUA_GCCOUNT, 0);
|
||||
ffi::lua_pushnumber(state, n as ffi::lua_Number);
|
||||
return 1;
|
||||
}
|
||||
// TODO: More variants
|
||||
_ => ffi::luaL_error(
|
||||
state,
|
||||
cstr!("collectgarbage must be called with 'count' or 'collect'"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
self.globals().raw_set(
|
||||
"collectgarbage",
|
||||
self.create_c_function(lua_collectgarbage)?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn make_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 1);
|
||||
|
@ -2740,7 +2815,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
|
|||
// For source code, first try interpreting the lua as an expression by adding
|
||||
// "return", then as a statement. This is the same thing the
|
||||
// actual lua repl does.
|
||||
if self.source.starts_with(ffi::LUA_SIGNATURE) {
|
||||
if self.source[0] < b'\n' {
|
||||
self.call(())
|
||||
} else if let Ok(function) = self.lua.load_chunk(
|
||||
&self.expression_source(),
|
||||
|
@ -2768,7 +2843,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
|
|||
'lua: 'fut,
|
||||
R: FromLuaMulti<'lua> + 'fut,
|
||||
{
|
||||
if self.source.starts_with(ffi::LUA_SIGNATURE) {
|
||||
if self.source[0] < b'\n' {
|
||||
self.call_async(())
|
||||
} else if let Ok(function) = self.lua.load_chunk(
|
||||
&self.expression_source(),
|
||||
|
@ -2886,9 +2961,9 @@ where
|
|||
let prealloc_failure = match extra.wrapped_failures_cache.pop() {
|
||||
Some(index) => PreallocatedFailure::Cached(index),
|
||||
None => {
|
||||
let ud = ffi::lua_newuserdata(state, mem::size_of::<WrappedFailure>());
|
||||
let ud = WrappedFailure::new_userdata(state);
|
||||
ffi::lua_rotate(state, 1, 1);
|
||||
PreallocatedFailure::New(ud as *mut WrappedFailure)
|
||||
PreallocatedFailure::New(ud)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3006,7 +3081,12 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<
|
|||
#[cfg(feature = "luajit")]
|
||||
let _gc_guard = GcGuard::new(state);
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "luau"
|
||||
))]
|
||||
{
|
||||
if libs.contains(StdLib::COROUTINE) {
|
||||
requiref(state, ffi::LUA_COLIBNAME, ffi::luaopen_coroutine, 1)?;
|
||||
|
@ -3019,6 +3099,7 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<
|
|||
ffi::lua_pop(state, 1);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
if libs.contains(StdLib::IO) {
|
||||
requiref(state, ffi::LUA_IOLIBNAME, ffi::luaopen_io, 1)?;
|
||||
ffi::lua_pop(state, 1);
|
||||
|
@ -3034,7 +3115,7 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<
|
|||
ffi::lua_pop(state, 1);
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53"))]
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
|
||||
{
|
||||
if libs.contains(StdLib::UTF8) {
|
||||
requiref(state, ffi::LUA_UTF8LIBNAME, ffi::luaopen_utf8, 1)?;
|
||||
|
@ -3042,7 +3123,7 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "lua52")]
|
||||
#[cfg(any(feature = "lua52", feature = "luau"))]
|
||||
{
|
||||
if libs.contains(StdLib::BIT) {
|
||||
requiref(state, ffi::LUA_BITLIBNAME, ffi::luaopen_bit32, 1)?;
|
||||
|
@ -3068,6 +3149,7 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<
|
|||
ffi::lua_pop(state, 1);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
if libs.contains(StdLib::PACKAGE) {
|
||||
requiref(state, ffi::LUA_LOADLIBNAME, ffi::luaopen_package, 1)?;
|
||||
ffi::lua_pop(state, 1);
|
||||
|
@ -3089,7 +3171,6 @@ unsafe fn load_from_std_lib(state: *mut ffi::lua_State, libs: StdLib) -> Result<
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// We move `extra` (`MutexGuard`) here to correctly drop it if panic
|
||||
unsafe fn ref_stack_pop(extra: &mut ExtraData) -> c_int {
|
||||
if let Some(free) = extra.ref_free.pop() {
|
||||
ffi::lua_replace(extra.ref_thread, free);
|
||||
|
@ -3238,7 +3319,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
.push((meta.into(), Self::box_method_mut(method)));
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(feature = "lua51")))]
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_method<S, A, R, M, MR>(&mut self, meta: S, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
|
@ -3274,7 +3355,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
|||
.push((meta.into(), Self::box_function_mut(function)));
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(feature = "lua51")))]
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_function<S, A, R, F, FR>(&mut self, meta: S, function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
|
|
42
src/scope.rs
42
src/scope.rs
|
@ -3,7 +3,6 @@ use std::cell::{Cell, RefCell};
|
|||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
|
@ -18,8 +17,8 @@ use crate::userdata::{
|
|||
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
||||
};
|
||||
use crate::util::{
|
||||
assert_stack, check_stack, get_userdata, init_userdata_metatable, push_table, rawset_field,
|
||||
take_userdata, StackGuard,
|
||||
assert_stack, check_stack, get_userdata, init_userdata_metatable, push_table, push_userdata,
|
||||
rawset_field, take_userdata, StackGuard,
|
||||
};
|
||||
use crate::value::{FromLua, FromLuaMulti, MultiValue, ToLua, ToLuaMulti, Value};
|
||||
|
||||
|
@ -206,7 +205,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
ffi::lua_pushnil(state);
|
||||
ffi::lua_setiuservalue(state, -2, i as c_int);
|
||||
}
|
||||
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushnil(state);
|
||||
ffi::lua_setuservalue(state, -2);
|
||||
|
@ -264,7 +263,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
fn wrap_method<'scope, 'lua, 'callback: 'scope, T: 'scope>(
|
||||
scope: &Scope<'lua, 'scope>,
|
||||
data: Rc<RefCell<T>>,
|
||||
data_ptr: *const c_void,
|
||||
ud_ptr: *const c_void,
|
||||
method: NonStaticMethod<'callback, T>,
|
||||
) -> Result<Function<'lua>> {
|
||||
// On methods that actually receive the userdata, we fake a type check on the passed in
|
||||
|
@ -280,7 +279,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
lua.push_userdata_ref(&ud.0)?;
|
||||
if get_userdata(lua.state, -1) as *const _ == data_ptr {
|
||||
if get_userdata(lua.state, -1) as *const _ == ud_ptr {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -336,8 +335,9 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 13)?;
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[allow(clippy::let_and_return)]
|
||||
let data_ptr = protect_lua!(lua.state, 0, 1, |state| {
|
||||
let ud_ptr = protect_lua!(lua.state, 0, 1, |state| {
|
||||
let ud =
|
||||
ffi::lua_newuserdata(state, mem::size_of::<UserDataCell<Rc<RefCell<T>>>>());
|
||||
|
||||
|
@ -350,13 +350,22 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
|
||||
ud
|
||||
})?;
|
||||
#[cfg(feature = "luau")]
|
||||
let ud_ptr = {
|
||||
push_userdata::<UserDataCell<Rc<RefCell<T>>>>(
|
||||
lua.state,
|
||||
UserDataCell::new(data.clone()),
|
||||
)?;
|
||||
ffi::lua_touserdata(lua.state, -1)
|
||||
};
|
||||
|
||||
// Prepare metatable, add meta methods first and then meta fields
|
||||
let meta_methods_nrec = ud_methods.meta_methods.len() + ud_fields.meta_fields.len() + 1;
|
||||
push_table(lua.state, 0, meta_methods_nrec as c_int)?;
|
||||
|
||||
for (k, m) in ud_methods.meta_methods {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, data_ptr, m)?))?;
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, k.validate()?.name())?;
|
||||
}
|
||||
for (k, f) in ud_fields.meta_fields {
|
||||
|
@ -371,7 +380,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
push_table(lua.state, 0, field_getters_nrec as c_int)?;
|
||||
for (k, m) in ud_fields.field_getters {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, data_ptr, m)?))?;
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, &k)?;
|
||||
}
|
||||
field_getters_index = Some(ffi::lua_absindex(lua.state, -1));
|
||||
|
@ -383,7 +392,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
push_table(lua.state, 0, field_setters_nrec as c_int)?;
|
||||
for (k, m) in ud_fields.field_setters {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, data_ptr, m)?))?;
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, &k)?;
|
||||
}
|
||||
field_setters_index = Some(ffi::lua_absindex(lua.state, -1));
|
||||
|
@ -396,7 +405,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
push_table(lua.state, 0, methods_nrec as c_int)?;
|
||||
for (k, m) in ud_methods.methods {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, data_ptr, m)?))?;
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, &k)?;
|
||||
}
|
||||
methods_index = Some(ffi::lua_absindex(lua.state, -1));
|
||||
|
@ -417,7 +426,8 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
|
||||
let mt_ptr = ffi::lua_topointer(lua.state, -1);
|
||||
// Write userdata just before attaching metatable with `__gc` metamethod
|
||||
ptr::write(data_ptr as _, UserDataCell::new(data));
|
||||
#[cfg(not(feature = "luau"))]
|
||||
std::ptr::write(ud_ptr as _, UserDataCell::new(data));
|
||||
ffi::lua_setmetatable(lua.state, -2);
|
||||
let ud = AnyUserData(lua.pop_ref());
|
||||
lua.register_userdata_metatable(mt_ptr, None);
|
||||
|
@ -446,7 +456,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
ffi::lua_pushnil(state);
|
||||
ffi::lua_setiuservalue(state, -2, i as c_int);
|
||||
}
|
||||
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushnil(state);
|
||||
ffi::lua_setuservalue(state, -2);
|
||||
|
@ -532,7 +542,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
// First, get the environment table
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
ffi::lua_getupvalue(state, -1, 1);
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||
ffi::lua_getfenv(state, -1);
|
||||
|
||||
// Second, get the `get_poll()` closure using the corresponding key
|
||||
|
@ -727,7 +737,7 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
));
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(feature = "lua51")))]
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_method<S, A, R, M, MR>(&mut self, _meta: S, _method: M)
|
||||
where
|
||||
T: Clone,
|
||||
|
@ -772,7 +782,7 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'l
|
|||
));
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(feature = "lua51")))]
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_function<S, A, R, F, FR>(&mut self, _meta: S, _function: F)
|
||||
where
|
||||
S: Into<MetaMethod>,
|
||||
|
|
|
@ -9,11 +9,17 @@ impl StdLib {
|
|||
/// [`coroutine`](https://www.lua.org/manual/5.4/manual.html#6.2) library
|
||||
///
|
||||
/// Requires `feature = "lua54/lua53/lua52"`
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "luau"
|
||||
))]
|
||||
pub const COROUTINE: StdLib = StdLib(1);
|
||||
/// [`table`](https://www.lua.org/manual/5.4/manual.html#6.6) library
|
||||
pub const TABLE: StdLib = StdLib(1 << 1);
|
||||
/// [`io`](https://www.lua.org/manual/5.4/manual.html#6.8) library
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub const IO: StdLib = StdLib(1 << 2);
|
||||
/// [`os`](https://www.lua.org/manual/5.4/manual.html#6.9) library
|
||||
pub const OS: StdLib = StdLib(1 << 3);
|
||||
|
@ -22,16 +28,17 @@ impl StdLib {
|
|||
/// [`utf8`](https://www.lua.org/manual/5.4/manual.html#6.5) library
|
||||
///
|
||||
/// Requires `feature = "lua54/lua53"`
|
||||
#[cfg(any(feature = "lua54", feature = "lua53"))]
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
|
||||
pub const UTF8: StdLib = StdLib(1 << 5);
|
||||
/// [`bit`](https://www.lua.org/manual/5.2/manual.html#6.7) library
|
||||
///
|
||||
/// Requires `feature = "lua52/luajit"`
|
||||
#[cfg(any(feature = "lua52", feature = "luajit", doc))]
|
||||
#[cfg(any(feature = "lua52", feature = "luajit", feature = "luau", doc))]
|
||||
pub const BIT: StdLib = StdLib(1 << 6);
|
||||
/// [`math`](https://www.lua.org/manual/5.4/manual.html#6.7) library
|
||||
pub const MATH: StdLib = StdLib(1 << 7);
|
||||
/// [`package`](https://www.lua.org/manual/5.4/manual.html#6.3) library
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub const PACKAGE: StdLib = StdLib(1 << 8);
|
||||
/// [`jit`](http://luajit.org/ext_jit.html) library
|
||||
///
|
||||
|
|
|
@ -11,6 +11,7 @@ use futures_core::future::LocalBoxFuture;
|
|||
|
||||
use crate::error::Result;
|
||||
use crate::ffi;
|
||||
#[cfg(not(feature = "luau"))]
|
||||
use crate::hook::Debug;
|
||||
use crate::lua::Lua;
|
||||
use crate::util::{assert_stack, StackGuard};
|
||||
|
@ -48,11 +49,10 @@ pub(crate) struct AsyncPollUpvalue<'lua> {
|
|||
pub(crate) lua: Lua,
|
||||
pub(crate) fut: LocalBoxFuture<'lua, Result<MultiValue<'lua>>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "send")]
|
||||
#[cfg(all(feature = "send", not(feature = "luau")))]
|
||||
pub(crate) type HookCallback = Arc<Mutex<dyn FnMut(&Lua, Debug) -> Result<()> + Send>>;
|
||||
|
||||
#[cfg(not(feature = "send"))]
|
||||
#[cfg(all(not(feature = "send"), not(feature = "luau")))]
|
||||
pub(crate) type HookCallback = Arc<Mutex<dyn FnMut(&Lua, Debug) -> Result<()>>>;
|
||||
|
||||
#[cfg(all(feature = "send", feature = "lua54"))]
|
||||
|
|
|
@ -419,7 +419,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// Requires `feature = "async"`
|
||||
///
|
||||
/// [`add_meta_method`]: #method.add_meta_method
|
||||
#[cfg(all(feature = "async", not(feature = "lua51")))]
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||
fn add_async_meta_method<S, A, R, M, MR>(&mut self, name: S, method: M)
|
||||
where
|
||||
|
@ -461,7 +461,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
|||
/// Requires `feature = "async"`
|
||||
///
|
||||
/// [`add_meta_function`]: #method.add_meta_function
|
||||
#[cfg(all(feature = "async", not(feature = "lua51")))]
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||
fn add_async_meta_function<S, A, R, F, FR>(&mut self, name: S, function: F)
|
||||
where
|
||||
|
@ -839,7 +839,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
ffi::lua_pushnil(lua.state);
|
||||
ffi::lua_setiuservalue(lua.state, -2, i as c_int);
|
||||
}
|
||||
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(feature = "lua53", feature = "lua52", feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushnil(lua.state);
|
||||
ffi::lua_setuservalue(lua.state, -2);
|
||||
|
@ -865,6 +865,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
///
|
||||
/// [`get_user_value`]: #method.get_user_value
|
||||
/// [`set_nth_user_value`]: #method.set_nth_user_value
|
||||
// #[cfg(not(feature = "luau"))]
|
||||
#[inline]
|
||||
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
|
||||
self.set_nth_user_value(1, v)
|
||||
|
@ -876,6 +877,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
///
|
||||
/// [`set_user_value`]: #method.set_user_value
|
||||
/// [`get_nth_user_value`]: #method.get_nth_user_value
|
||||
// #[cfg(not(feature = "luau"))]
|
||||
#[inline]
|
||||
pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
|
||||
self.get_nth_user_value(1)
|
||||
|
@ -891,6 +893,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// For other Lua versions this functionality is provided using a wrapping table.
|
||||
///
|
||||
/// [`get_nth_user_value`]: #method.get_nth_user_value
|
||||
// #[cfg(not(feature = "luau"))]
|
||||
pub fn set_nth_user_value<V: ToLua<'lua>>(&self, n: usize, v: V) -> Result<()> {
|
||||
if n < 1 || n > u16::MAX as usize {
|
||||
return Err(Error::RuntimeError(
|
||||
|
@ -945,6 +948,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// For other Lua versions this functionality is provided using a wrapping table.
|
||||
///
|
||||
/// [`set_nth_user_value`]: #method.set_nth_user_value
|
||||
// #[cfg(not(feature = "luau"))]
|
||||
pub fn get_nth_user_value<V: FromLua<'lua>>(&self, n: usize) -> Result<V> {
|
||||
if n < 1 || n > u16::MAX as usize {
|
||||
return Err(Error::RuntimeError(
|
||||
|
@ -986,6 +990,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// The value can be retrieved with [`get_named_user_value`].
|
||||
///
|
||||
/// [`get_named_user_value`]: #method.get_named_user_value
|
||||
// #[cfg(not(feature = "luau"))]
|
||||
pub fn set_named_user_value<S, V>(&self, name: &S, v: V) -> Result<()>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
|
@ -1025,6 +1030,7 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// Returns an associated value by name set by [`set_named_user_value`].
|
||||
///
|
||||
/// [`set_named_user_value`]: #method.set_named_user_value
|
||||
// #[cfg(not(feature = "luau"))]
|
||||
pub fn get_named_user_value<S, V>(&self, name: &S) -> Result<V>
|
||||
where
|
||||
S: AsRef<[u8]> + ?Sized,
|
||||
|
|
56
src/util.rs
56
src/util.rs
|
@ -278,6 +278,7 @@ where
|
|||
}
|
||||
|
||||
// Internally uses 3 stack spaces, does not call checkstack.
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[inline]
|
||||
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T) -> Result<()> {
|
||||
let ud = protect_lua!(state, 0, 1, |state| {
|
||||
|
@ -287,6 +288,27 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Internally uses 3 stack spaces, does not call checkstack.
|
||||
#[cfg(feature = "luau")]
|
||||
#[inline]
|
||||
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T) -> Result<()> {
|
||||
unsafe extern "C" fn destructor<T>(ud: *mut c_void) {
|
||||
let ud = ud as *mut T;
|
||||
if *(ud.offset(1) as *mut u8) == 0 {
|
||||
ptr::drop_in_place(ud);
|
||||
}
|
||||
}
|
||||
|
||||
let ud = protect_lua!(state, 0, 1, |state| {
|
||||
let size = mem::size_of::<T>() + 1;
|
||||
ffi::lua_newuserdatadtor(state, size, destructor::<T>) as *mut T
|
||||
})?;
|
||||
ptr::write(ud, t);
|
||||
*(ud.offset(1) as *mut u8) = 0; // Mark as not destructed
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Internally uses 3 stack spaces, does not call checkstack.
|
||||
#[cfg(feature = "lua54")]
|
||||
#[inline]
|
||||
|
@ -316,8 +338,11 @@ pub unsafe fn take_userdata<T>(state: *mut ffi::lua_State) -> T {
|
|||
// after the first call to __gc.
|
||||
get_destructed_userdata_metatable(state);
|
||||
ffi::lua_setmetatable(state, -2);
|
||||
let ud = get_userdata(state, -1);
|
||||
let ud = get_userdata::<T>(state, -1);
|
||||
ffi::lua_pop(state, 1);
|
||||
if cfg!(feature = "luau") {
|
||||
*(ud.offset(1) as *mut u8) = 1; // Mark as destructed
|
||||
}
|
||||
ptr::read(ud)
|
||||
}
|
||||
|
||||
|
@ -508,8 +533,11 @@ pub unsafe fn init_userdata_metatable<T>(
|
|||
rawset_field(state, -2, "__newindex")?;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
|
||||
rawset_field(state, -2, "__gc")?;
|
||||
}
|
||||
|
||||
ffi::lua_pushboolean(state, 0);
|
||||
rawset_field(state, -2, "__metatable")?;
|
||||
|
@ -519,6 +547,7 @@ pub unsafe fn init_userdata_metatable<T>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
pub unsafe extern "C" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
|
||||
// It's probably NOT a good idea to catch Rust panics in finalizer
|
||||
// Lua 5.4 ignores it, other versions generates `LUA_ERRGCMM` without calling message handler
|
||||
|
@ -553,7 +582,7 @@ where
|
|||
|
||||
// We cannot shadow Rust errors with Lua ones, we pre-allocate enough memory
|
||||
// to store a wrapped error or panic *before* we proceed.
|
||||
let ud = ffi::lua_newuserdata(state, mem::size_of::<WrappedFailure>());
|
||||
let ud = WrappedFailure::new_userdata(state);
|
||||
ffi::lua_rotate(state, 1, 1);
|
||||
|
||||
match catch_unwind(AssertUnwindSafe(|| f(nargs))) {
|
||||
|
@ -706,6 +735,8 @@ pub unsafe fn get_main_state(state: *mut ffi::lua_State) -> Option<*mut ffi::lua
|
|||
None
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "luau")]
|
||||
Some(ffi::lua_mainthread(state))
|
||||
}
|
||||
|
||||
// Initialize the internal (with __gc method) metatable for a type T.
|
||||
|
@ -718,8 +749,11 @@ pub unsafe fn init_gc_metatable<T: Any>(
|
|||
|
||||
push_table(state, 0, 3)?;
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
{
|
||||
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
|
||||
rawset_field(state, -2, "__gc")?;
|
||||
}
|
||||
|
||||
ffi::lua_pushboolean(state, 0);
|
||||
rawset_field(state, -2, "__metatable")?;
|
||||
|
@ -879,10 +913,28 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<()> {
|
|||
}
|
||||
|
||||
pub(crate) enum WrappedFailure {
|
||||
None,
|
||||
Error(Error),
|
||||
Panic(Option<Box<dyn Any + Send + 'static>>),
|
||||
}
|
||||
|
||||
impl WrappedFailure {
|
||||
pub(crate) unsafe fn new_userdata(state: *mut ffi::lua_State) -> *mut Self {
|
||||
let size = mem::size_of::<WrappedFailure>();
|
||||
#[cfg(feature = "luau")]
|
||||
let ud = {
|
||||
unsafe extern "C" fn destructor(p: *mut c_void) {
|
||||
ptr::drop_in_place(p as *mut WrappedFailure);
|
||||
}
|
||||
ffi::lua_newuserdatadtor(state, size, destructor) as *mut Self
|
||||
};
|
||||
#[cfg(not(feature = "luau"))]
|
||||
let ud = ffi::lua_newuserdata(state, size) as *mut Self;
|
||||
ptr::write(ud, WrappedFailure::None);
|
||||
ud
|
||||
}
|
||||
}
|
||||
|
||||
// Converts the given lua value to a string in a reasonable format without causing a Lua error or
|
||||
// panicking.
|
||||
pub(crate) unsafe fn to_string(state: *mut ffi::lua_State, index: c_int) -> String {
|
||||
|
|
|
@ -299,7 +299,7 @@ async fn test_async_userdata() -> Result<()> {
|
|||
Ok(format!("elapsed:{}ms", n))
|
||||
});
|
||||
|
||||
#[cfg(not(feature = "lua51"))]
|
||||
#[cfg(not(any(feature = "lua51", feature = "luau")))]
|
||||
methods.add_async_meta_method(mlua::MetaMethod::Call, |_, data, ()| async move {
|
||||
let n = data.0.load(Ordering::Relaxed);
|
||||
Delay::new(Duration::from_millis(n)).await;
|
||||
|
@ -363,7 +363,7 @@ async fn test_async_userdata() -> Result<()> {
|
|||
.exec_async()
|
||||
.await?;
|
||||
|
||||
#[cfg(not(feature = "lua51"))]
|
||||
#[cfg(not(any(feature = "lua51", feature = "luau")))]
|
||||
lua.load(
|
||||
r#"
|
||||
userdata:set_value(15)
|
||||
|
|
|
@ -93,6 +93,7 @@ fn test_c_function() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[test]
|
||||
fn test_dump() -> Result<()> {
|
||||
let lua = unsafe { Lua::unsafe_new() };
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![cfg(not(feature = "luau"))]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
|
|
@ -41,7 +41,12 @@ fn test_gc_control() -> Result<()> {
|
|||
#[cfg(feature = "lua54")]
|
||||
assert_eq!(lua.gc_gen(0, 0), mlua::GCMode::Incremental);
|
||||
|
||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||
#[cfg(any(
|
||||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "luau"
|
||||
))]
|
||||
{
|
||||
assert!(lua.gc_is_running());
|
||||
lua.gc_stop();
|
||||
|
|
|
@ -11,6 +11,7 @@ use mlua::{
|
|||
UserData, Value, Variadic,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[test]
|
||||
fn test_safety() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
@ -120,6 +121,7 @@ fn test_exec() -> Result<()> {
|
|||
"#,
|
||||
)
|
||||
.eval()?;
|
||||
println!("checkpoint");
|
||||
assert!(module.contains_key("func")?);
|
||||
assert_eq!(
|
||||
module.get::<_, Function>("func")?.call::<_, String>(())?,
|
||||
|
@ -150,6 +152,7 @@ fn test_eval() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[test]
|
||||
fn test_load_mode() -> Result<()> {
|
||||
let lua = unsafe { Lua::unsafe_new() };
|
||||
|
@ -250,15 +253,7 @@ fn test_error() -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
impl error::Error for TestError {
|
||||
fn description(&self) -> &str {
|
||||
"test error"
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&dyn error::Error> {
|
||||
None
|
||||
}
|
||||
}
|
||||
impl error::Error for TestError {}
|
||||
|
||||
let lua = Lua::new();
|
||||
|
||||
|
@ -295,8 +290,8 @@ fn test_error() -> Result<()> {
|
|||
end, 3)
|
||||
|
||||
local function handler(err)
|
||||
if string.match(_VERSION, ' 5%.1$') or string.match(_VERSION, ' 5%.2$') then
|
||||
-- Special case for Lua 5.1/5.2
|
||||
if string.match(_VERSION, ' 5%.1$') or string.match(_VERSION, ' 5%.2$') or _VERSION == "Luau" then
|
||||
-- Special case for Lua 5.1/5.2 and Luau
|
||||
local caps = string.match(err, ': (%d+)$')
|
||||
if caps then
|
||||
err = caps
|
||||
|
@ -1096,7 +1091,11 @@ fn test_context_thread() -> Result<()> {
|
|||
))]
|
||||
f.call::<_, ()>(lua.current_thread())?;
|
||||
|
||||
#[cfg(any(feature = "lua51", all(feature = "luajit", not(feature = "luajit52"))))]
|
||||
#[cfg(any(
|
||||
feature = "lua51",
|
||||
all(feature = "luajit", not(feature = "luajit52")),
|
||||
feature = "luau"
|
||||
))]
|
||||
f.call::<_, ()>(Nil)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -1170,6 +1169,7 @@ fn test_load_from_function() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[test]
|
||||
fn test_inspect_stack() -> Result<()> {
|
||||
let lua = Lua::new();
|
||||
|
|
|
@ -155,7 +155,8 @@ fn test_coroutine_from_closure() -> Result<()> {
|
|||
feature = "lua54",
|
||||
feature = "lua53",
|
||||
feature = "lua52",
|
||||
feature = "luajit"
|
||||
feature = "luajit",
|
||||
feature = "luau"
|
||||
))]
|
||||
let thrd: Thread = lua.load("coroutine.create(main)").eval()?;
|
||||
#[cfg(feature = "lua51")]
|
||||
|
|
|
@ -350,7 +350,7 @@ fn test_userdata_take() -> Result<()> {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_destroy_userdata() -> Result<()> {
|
||||
fn test_userdata_destroy() -> Result<()> {
|
||||
struct MyUserdata(Arc<()>);
|
||||
|
||||
impl UserData for MyUserdata {}
|
||||
|
@ -358,12 +358,15 @@ fn test_destroy_userdata() -> Result<()> {
|
|||
let rc = Arc::new(());
|
||||
|
||||
let lua = Lua::new();
|
||||
lua.globals().set("userdata", MyUserdata(rc.clone()))?;
|
||||
let ud = lua.create_userdata(MyUserdata(rc.clone()))?;
|
||||
ud.set_user_value(MyUserdata(rc.clone()))?;
|
||||
lua.globals().set("userdata", ud)?;
|
||||
|
||||
assert_eq!(Arc::strong_count(&rc), 2);
|
||||
assert_eq!(Arc::strong_count(&rc), 3);
|
||||
|
||||
// should destroy all objects
|
||||
let _ = lua.globals().raw_remove("userdata")?;
|
||||
// Should destroy all objects
|
||||
lua.globals().raw_remove("userdata")?;
|
||||
lua.gc_collect()?;
|
||||
lua.gc_collect()?;
|
||||
|
||||
assert_eq!(Arc::strong_count(&rc), 1);
|
||||
|
|
Loading…
Reference in New Issue