diff --git a/Cargo.toml b/Cargo.toml index 61e6e19..eb550f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 } -luau0-src = { version = "1", optional = true, git = "https://github.com/khvzak/luau-src-rs.git" } +luau0-src = { version = "0.1.0", optional = true } [dev-dependencies] rustyline = "9.0" diff --git a/src/ffi/lauxlib.rs b/src/ffi/lauxlib.rs deleted file mode 100644 index a543a7d..0000000 --- a/src/ffi/lauxlib.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Contains definitions from `lauxlib.h`. - -use std::os::raw::c_int; - -#[cfg(feature = "lua54")] -pub use super::lua54::lauxlib::*; - -#[cfg(feature = "lua53")] -pub use super::lua53::lauxlib::*; - -#[cfg(feature = "lua52")] -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}; - -#[cfg(any(feature = "lua51", feature = "luajit"))] -pub use super::compat53::{ - luaL_checkstack, luaL_getmetafield, luaL_getsubtable, luaL_len, luaL_loadbufferx, - luaL_newmetatable, luaL_requiref, luaL_setfuncs, luaL_setmetatable, luaL_testudata, - 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; diff --git a/src/ffi/lua.rs b/src/ffi/lua.rs deleted file mode 100644 index d918443..0000000 --- a/src/ffi/lua.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! Contains definitions from `lua.h`. - -use std::os::raw::c_int; - -#[cfg(feature = "lua54")] -pub use super::lua54::lua::*; - -#[cfg(feature = "lua53")] -pub use super::lua53::lua::*; - -#[cfg(feature = "lua52")] -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, - lua_getuservalue, lua_isinteger, lua_pushlstring, lua_rawget, lua_rawgeti, lua_rawgetp, - lua_rawseti, lua_rotate, lua_seti, lua_stringtonumber, lua_tointeger, lua_tointegerx, - LUA_EXTRASPACE, -}; - -#[cfg(any(feature = "lua51", feature = "luajit"))] -pub use super::compat53::{ - lua_absindex, lua_arith, lua_compare, lua_copy, lua_dump, 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, 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; - -#[cfg(any(feature = "lua51", all(feature = "luajit", not(feature = "vendored"))))] -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 -// - -#[cfg(any( - feature = "lua53", - feature = "lua52", - feature = "lua51", - feature = "luajit", - feature = "luau" -))] -#[inline(always)] -pub unsafe fn lua_resume( - L: *mut lua_State, - from: *mut lua_State, - narg: c_int, - nres: *mut c_int, -) -> c_int { - #[cfg(any(feature = "lua51", feature = "luajit"))] - let _ = from; - #[cfg(any(feature = "lua51", feature = "luajit"))] - let ret = lua_resume_(L, narg); - - #[cfg(any(feature = "lua53", feature = "lua52", feature = "luau"))] - let ret = lua_resume_(L, from, narg); - - if (ret == LUA_OK || ret == LUA_YIELD) && !(nres.is_null()) { - *nres = lua_gettop(L); - } - ret -} - -#[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; - lua_resetthread(th) - } -} diff --git a/src/ffi/compat53.rs b/src/ffi/lua51/compat.rs similarity index 50% rename from src/ffi/compat53.rs rename to src/ffi/lua51/compat.rs index 8d0fdba..99a575b 100644 --- a/src/ffi/compat53.rs +++ b/src/ffi/lua51/compat.rs @@ -1,25 +1,16 @@ -//! Lua 5.3 compatibility layer for Lua 5.1/5.2 +//! MLua compatibility layer for Lua 5.1/JIT //! //! Based on github.com/keplerproject/lua-compat-5.3 -#![allow(clippy::needless_return)] - use std::convert::TryInto; -use std::ffi::CStr; use std::mem; use std::os::raw::{c_char, c_int, c_void}; use std::ptr; -use std::str::FromStr; -#[cfg(feature = "lua52")] -use super::lua52::*; - -#[cfg(any(feature = "lua51", feature = "luajit"))] -use super::lua51::*; - -#[cfg(feature = "luau")] -use super::luau::*; +use super::lua::*; +use super::lauxlib::*; +#[inline(always)] unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) { while a < b { lua_pushvalue(L, a); @@ -34,7 +25,6 @@ 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); @@ -47,28 +37,7 @@ unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int { while li < le { let m = (li + le) / 2; if lua_getstack(L, m, &mut ar) != 0 { - li = m + 1; - } else { - le = m; - } - } - 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; + li = m + 1 } else { le = m; } @@ -106,7 +75,6 @@ unsafe fn compat53_checkmode( LUA_OK } -#[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 @@ -132,21 +100,12 @@ unsafe fn compat53_findfield(L: *mut lua_State, objidx: c_int, level: c_int) -> } lua_pop(L, 1); // remove value } - return 0; // not found + 0 // not found } -#[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 { +unsafe fn compat53_pushglobalfuncname(L: *mut lua_State, ar: *mut lua_Debug) -> c_int { let top = lua_gettop(L); - // push function - #[cfg(not(feature = "luau"))] - lua_getinfo(L, cstr!("f"), ar); - #[cfg(feature = "luau")] - lua_getinfo(L, level, cstr!("f"), ar); + lua_getinfo(L, cstr!("f"), ar); // push function lua_pushvalue(L, LUA_GLOBALSINDEX); if compat53_findfield(L, top + 1, 2) != 0 { lua_copy(L, -1, top + 1); // move name to proper place @@ -158,35 +117,6 @@ unsafe fn compat53_pushglobalfuncname( } } -#[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 { // is there a name? @@ -195,7 +125,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, -1, ar) != 0 { + if compat53_pushglobalfuncname(L, ar) != 0 { lua_pushfstring(L, cstr!("function '%s'"), lua_tostring(L, -1)); lua_remove(L, -2); // remove name } else { @@ -211,31 +141,10 @@ unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) { } } -unsafe fn compat53_call_lua(L: *mut lua_State, code: &str, nargs: c_int, nret: c_int) { - lua_rawgetp(L, LUA_REGISTRYINDEX, code.as_ptr() as *const c_void); - if lua_type(L, -1) != LUA_TFUNCTION { - lua_pop(L, 1); - if luaL_loadbuffer( - L, - code.as_ptr() as *const c_char, - code.as_bytes().len(), - cstr!("=none"), - ) != 0 - { - lua_error(L); - } - lua_pushvalue(L, -1); - lua_rawsetp(L, LUA_REGISTRYINDEX, code.as_ptr() as *const c_void); - } - lua_insert(L, -nargs - 1); - lua_call(L, nargs, nret); -} - // // lua ported functions // -#[cfg(any(feature = "lua51", feature = "luajit"))] #[inline(always)] pub unsafe fn lua_absindex(L: *mut lua_State, mut idx: c_int) -> c_int { if idx < 0 && idx > LUA_REGISTRYINDEX { @@ -244,50 +153,6 @@ pub unsafe fn lua_absindex(L: *mut lua_State, mut idx: c_int) -> c_int { idx } -// Comparison and arithmetic functions -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPADD: c_int = 0; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPSUB: c_int = 1; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPMUL: c_int = 2; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPDIV: c_int = 3; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPMOD: c_int = 4; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPPOW: c_int = 5; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPUNM: c_int = 6; - -#[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 -elseif op == 1 then return a-b -elseif op == 2 then return a*b -elseif op == 3 then return a/b -elseif op == 4 then return a%b -elseif op == 5 then return a^b -elseif op == 6 then return -a -end -"#; - -#[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 { - luaL_error(L, cstr!("invalid 'op' argument for lua_arith")); - } - luaL_checkstack(L, 5, cstr!("not enough stack slots")); - if op == LUA_OPUNM { - lua_pushvalue(L, -1); - } - lua_pushnumber(L, op as lua_Number); - lua_insert(L, -3); - compat53_call_lua(L, COMPAT53_ARITH_CODE, 3, 1); -} - pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) { idx = lua_absindex(L, idx); let n_elems = lua_gettop(L) - idx + 1; @@ -303,7 +168,6 @@ pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) { } } -#[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); @@ -321,42 +185,23 @@ pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int { return 1; } } - return 0; + 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()) } -#[cfg(any(feature = "lua51", feature = "luajit"))] #[inline(always)] pub unsafe fn lua_tonumberx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Number { let n = lua_tonumber(L, i); if !isnum.is_null() { - *isnum = if n != 0.0 || lua_isnumber(L, i) != 0 { - 1 - } else { - 0 - }; + *isnum = (n != 0.0 || lua_isnumber(L, i) != 0) as c_int; } - return n; + n } -// 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; @@ -371,44 +216,14 @@ pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> if !isnum.is_null() { *isnum = 0; } - return 0; + 0 } -#[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", feature = "luau"))] -pub const LUA_OPEQ: c_int = 0; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPLT: c_int = 1; -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] -pub const LUA_OPLE: c_int = 2; - -#[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 { - LUA_OPEQ => lua_equal(L, idx1, idx2), - LUA_OPLT => lua_lessthan(L, idx1, idx2), - LUA_OPLE => { - luaL_checkstack(L, 5, cstr!("not enough stack slots")); - idx1 = lua_absindex(L, idx1); - idx2 = lua_absindex(L, idx2); - lua_pushvalue(L, idx1); - lua_pushvalue(L, idx2); - compat53_call_lua(L, "local a,b=...\nreturn a<=b\n", 2, 1); - let result = lua_toboolean(L, -1); - lua_pop(L, 1); - result - } - _ => luaL_error(L, cstr!("invalid 'op' argument for lua_compare")), - } -} - -#[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 { @@ -419,17 +234,6 @@ pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> lua_tostring(L, -1) } -#[cfg(feature = "lua52")] -#[inline(always)] -pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char { - if l == 0 { - lua_pushlstring_(L, cstr!(""), 0) - } else { - lua_pushlstring_(L, s, l) - } -} - -#[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); @@ -458,8 +262,7 @@ pub unsafe fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c pub unsafe fn lua_geti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) -> c_int { idx = lua_absindex(L, idx); lua_pushinteger(L, n); - lua_gettable(L, idx); - lua_type(L, -1) + lua_gettable(L, idx) } #[inline(always)] @@ -470,56 +273,24 @@ pub unsafe fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int { #[inline(always)] pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int { - lua_rawgeti_(L, idx, n.try_into().expect("cannot convert to lua_Integer")); + let n = n.try_into().expect("cannot convert index to lua_Integer"); + lua_rawgeti_(L, idx, n); lua_type(L, -1) } -#[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); lua_pushlightuserdata(L, p as *mut c_void); - lua_rawget(L, abs_i); - lua_type(L, -1) + lua_rawget(L, abs_i) } -#[cfg(feature = "lua52")] -#[inline(always)] -pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int { - lua_rawgetp_(L, idx, p); - lua_type(L, -1) -} - -#[cfg(any(feature = "lua51", feature = "luajit"))] #[inline(always)] pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int { lua_getfenv(L, idx); 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 { - lua_getuservalue_(L, idx); - lua_type(L, -1) -} - #[inline(always)] pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) { luaL_checkstack(L, 1, cstr!("not enough stack slots available")); @@ -531,14 +302,10 @@ pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) { #[inline(always)] pub unsafe fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer) { - lua_rawseti_( - L, - idx, - n.try_into().expect("cannot convert index from lua_Integer"), - ) + let n = n.try_into().expect("cannot convert index from lua_Integer"); + lua_rawseti_(L, idx, n) } -#[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); @@ -548,41 +315,12 @@ pub unsafe fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void) { lua_rawset(L, abs_i); } -#[cfg(any(feature = "lua51", feature = "luajit"))] #[inline(always)] pub unsafe fn lua_setuservalue(L: *mut lua_State, idx: c_int) { luaL_checktype(L, -1, LUA_TTABLE); 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, @@ -593,7 +331,6 @@ pub unsafe fn lua_dump( lua_dump_(L, writer, data) } -#[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) { @@ -616,83 +353,29 @@ pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) { } } -#[inline(always)] -pub unsafe fn lua_stringtonumber(L: *mut lua_State, s: *const c_char) -> usize { - let cs = CStr::from_ptr(s); - if let Ok(rs) = cs.to_str() { - if let Ok(n) = lua_Number::from_str(rs.trim()) { - lua_pushnumber(L, n); - return cs.to_bytes_with_nul().len(); - } - } - 0 -} - -pub const LUA_EXTRASPACE: usize = mem::size_of::<*const ()>(); - -#[allow(clippy::branches_sharing_code)] -pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void { - luaL_checkstack(L, 4, cstr!("not enough stack slots available")); - lua_pushliteral(L, "__compat53_extraspace"); - lua_pushvalue(L, -1); - lua_rawget(L, LUA_REGISTRYINDEX); - if lua_istable(L, -1) == 0 { - lua_pop(L, 1); - lua_createtable(L, 0, 2); - lua_createtable(L, 0, 1); - 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); - let is_main = lua_pushthread(L); - lua_rawget(L, -2); - let mut _ptr = lua_touserdata(L, -1); - if _ptr.is_null() { - lua_pop(L, 1); - _ptr = lua_newuserdata(L, LUA_EXTRASPACE); - if is_main != 0 { - // mem::size_of::() == 1 - ptr::write_bytes(_ptr, 0, LUA_EXTRASPACE); - lua_pushthread(L); - lua_pushvalue(L, -2); - lua_rawset(L, -4); - lua_pushboolean(L, 1); - lua_pushvalue(L, -2); - lua_rawset(L, -4); - } else { - lua_pushboolean(L, 1); - lua_rawget(L, -3); - let mptr = lua_touserdata(L, -1); - if !mptr.is_null() { - ptr::copy_nonoverlapping(mptr, _ptr, LUA_EXTRASPACE) - } else { - ptr::write_bytes(_ptr, 0, LUA_EXTRASPACE); - } - lua_pop(L, 1); - lua_pushthread(L); - lua_pushvalue(L, -2); - lua_rawset(L, -4); - } - } - lua_pop(L, 2); - return _ptr; -} - -#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] #[inline(always)] pub unsafe fn lua_pushglobaltable(L: *mut lua_State) { lua_pushvalue(L, LUA_GLOBALSINDEX); } +#[inline(always)] +pub unsafe fn lua_resume( + L: *mut lua_State, + _from: *mut lua_State, + narg: c_int, + nres: *mut c_int, +) -> c_int { + let ret = lua_resume_(L, narg); + if (ret == LUA_OK || ret == LUA_YIELD) && !(nres.is_null()) { + *nres = lua_gettop(L); + } + ret +} + // // lauxlib ported functions // -#[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 { @@ -717,7 +400,7 @@ pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) #[inline(always)] pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int { if luaL_newmetatable_(L, tname) != 0 { - lua_pushstring(L, tname); + lua_pushstring_(L, tname); lua_setfield(L, -2, cstr!("__name")); 1 } else { @@ -725,7 +408,6 @@ pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_in } } -#[cfg(any(feature = "lua51", feature = "luajit"))] #[inline(always)] pub unsafe fn luaL_loadbufferx( L: *mut lua_State, @@ -745,7 +427,6 @@ pub unsafe fn luaL_loadbufferx( luaL_loadbuffer(L, buff, sz, name) } -#[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; @@ -759,7 +440,6 @@ pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer { res } -#[cfg(any(feature = "lua51", feature = "luajit"))] pub unsafe fn luaL_traceback( L: *mut lua_State, L1: *mut lua_State, @@ -799,46 +479,6 @@ 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); @@ -875,7 +515,6 @@ 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", 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")); @@ -883,57 +522,19 @@ pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) { lua_setmetatable(L, -2); } -#[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); - luaL_checkstack(L, 2, cstr!("not enough stack slots")); - if p.is_null() || lua_getmetatable(L, i) == 0 { - return ptr::null_mut(); - } else { - luaL_getmetatable(L, tname); - let res = lua_rawequal(L, -1, -2); - lua_pop(L, 2); - if res == 0 { - p = ptr::null_mut(); - } - } - return p; -} - -#[cfg(any(feature = "lua51", feature = "luajit"))] -#[inline(always)] -pub unsafe fn luaL_setfuncs(L: *mut lua_State, mut l: *const luaL_Reg, nup: c_int) { - luaL_checkstack(L, nup + 1, cstr!("too many upvalues")); - while !(*l).name.is_null() { - // fill the table with given functions - l = l.offset(1); - lua_pushstring(L, (*l).name); - for _ in 0..nup { - // copy upvalues to the top - lua_pushvalue(L, -(nup + 1)); - } - lua_pushcclosure(L, (*l).func, nup); // closure with those upvalues - lua_settable(L, -(nup + 3)); // table must be below the upvalues, the name and the closure - } - lua_pop(L, nup); // remove upvalues -} - -#[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")); - lua_pushstring(L, fname); - lua_gettable(L, abs_i); - if lua_istable(L, -1) != 0 { + lua_pushstring_(L, fname); + if lua_gettable(L, abs_i) == LUA_TTABLE { return 1; } lua_pop(L, 1); lua_newtable(L); - lua_pushstring(L, fname); + lua_pushstring_(L, fname); lua_pushvalue(L, -2); lua_settable(L, abs_i); - return 0; + 0 } pub unsafe fn luaL_requiref( @@ -948,7 +549,7 @@ pub unsafe fn luaL_requiref( lua_pop(L, 1); lua_pushcfunction(L, openf); lua_pushstring(L, modname); - #[cfg(any(feature = "lua52", feature = "lua51", feature = "luau"))] + #[cfg(feature = "lua51")] { lua_call(L, 1, 1); lua_pushvalue(L, -1); @@ -960,7 +561,7 @@ pub unsafe fn luaL_requiref( lua_getfield(L, -1, modname); } } - if cfg!(any(feature = "lua52", feature = "lua51", feature = "luau")) && glb != 0 { + if cfg!(feature = "lua51") && glb != 0 { lua_pushvalue(L, -1); lua_setglobal(L, modname); } diff --git a/src/ffi/lua51/mod.rs b/src/ffi/lua51/mod.rs index c84fe4a..3f222bc 100644 --- a/src/ffi/lua51/mod.rs +++ b/src/ffi/lua51/mod.rs @@ -1,9 +1,11 @@ //! Low level bindings to Lua 5.1. -pub use self::lauxlib::*; -pub use self::lua::*; -pub use self::lualib::*; +pub use compat::*; +pub use lauxlib::*; +pub use lua::*; +pub use lualib::*; +pub mod compat; pub mod lauxlib; pub mod lua; pub mod lualib; diff --git a/src/ffi/lua52/compat.rs b/src/ffi/lua52/compat.rs new file mode 100644 index 0000000..7ff962d --- /dev/null +++ b/src/ffi/lua52/compat.rs @@ -0,0 +1,258 @@ +//! MLua compatibility layer for Lua 5.2 +//! +//! Based on github.com/keplerproject/lua-compat-5.3 + +use std::convert::TryInto; +use std::os::raw::{c_char, c_int, c_void}; +use std::ptr; + +use super::lauxlib::*; +use super::lua::*; + +#[inline(always)] +unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) { + while a < b { + lua_pushvalue(L, a); + lua_pushvalue(L, b); + lua_replace(L, a); + lua_replace(L, b); + a += 1; + b -= 1; + } +} + +// +// lua ported functions +// + +pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) { + idx = lua_absindex(L, idx); + let n_elems = lua_gettop(L) - idx + 1; + if n < 0 { + n += n_elems; + } + if n > 0 && n < n_elems { + luaL_checkstack(L, 2, cstr!("not enough stack slots available")); + n = n_elems - n; + compat53_reverse(L, idx, idx + n - 1); + compat53_reverse(L, idx + n, idx + n_elems - 1); + compat53_reverse(L, idx, idx + n_elems - 1); + } +} + +#[inline(always)] +pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int { + if lua_type(L, idx) == LUA_TNUMBER { + let n = lua_tonumber(L, idx); + let i = lua_tointeger(L, idx); + if (n - i as lua_Number).abs() < lua_Number::EPSILON { + return 1; + } + } + 0 +} + +#[inline(always)] +pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer { + lua_tointegerx(L, i, ptr::null_mut()) +} + +// Implemented for Lua 5.2 as well +// See https://github.com/keplerproject/lua-compat-5.3/issues/40 +#[inline(always)] +pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer { + let mut ok = 0; + let n = lua_tonumberx(L, i, &mut ok); + let n_int = n as lua_Integer; + if ok != 0 && (n - n_int as lua_Number).abs() < lua_Number::EPSILON { + if !isnum.is_null() { + *isnum = 1; + } + return n_int; + } + if !isnum.is_null() { + *isnum = 0; + } + 0 +} + +#[inline(always)] +pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char { + if l == 0 { + lua_pushlstring_(L, cstr!(""), 0) + } else { + lua_pushlstring_(L, s, l) + } +} + +#[inline(always)] +pub unsafe fn lua_getglobal(L: *mut lua_State, var: *const c_char) -> c_int { + lua_getglobal_(L, var); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int { + lua_gettable_(L, idx); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int { + lua_getfield_(L, idx, k); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_geti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) -> c_int { + idx = lua_absindex(L, idx); + lua_pushinteger(L, n); + lua_gettable(L, idx) +} + +#[inline(always)] +pub unsafe fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int { + lua_rawget_(L, idx); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int { + let n = n.try_into().expect("cannot convert index to lua_Integer"); + lua_rawgeti_(L, idx, n); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int { + lua_rawgetp_(L, idx, p); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int { + lua_getuservalue_(L, idx); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) { + luaL_checkstack(L, 1, cstr!("not enough stack slots available")); + idx = lua_absindex(L, idx); + lua_pushinteger(L, n); + lua_insert(L, -2); + lua_settable(L, idx); +} + +#[inline(always)] +pub unsafe fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer) { + let n = n.try_into().expect("cannot convert index from lua_Integer"); + lua_rawseti_(L, idx, n) +} + +#[inline(always)] +pub unsafe fn lua_dump( + L: *mut lua_State, + writer: lua_Writer, + data: *mut c_void, + _strip: c_int, +) -> c_int { + lua_dump_(L, writer, data) +} + +#[inline(always)] +pub unsafe fn lua_resume( + L: *mut lua_State, + from: *mut lua_State, + narg: c_int, + nres: *mut c_int, +) -> c_int { + let ret = lua_resume_(L, from, narg); + if (ret == LUA_OK || ret == LUA_YIELD) && !(nres.is_null()) { + *nres = lua_gettop(L); + } + ret +} + +// +// lauxlib ported functions +// + +#[inline(always)] +pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int { + if luaL_getmetafield_(L, obj, e) != 0 { + lua_type(L, -1) + } else { + LUA_TNIL + } +} + +#[inline(always)] +pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int { + if luaL_newmetatable_(L, tname) != 0 { + lua_pushstring(L, tname); + lua_setfield(L, -2, cstr!("__name")); + 1 + } else { + 0 + } +} + +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); + match t { + LUA_TNIL => { + lua_pushliteral(L, "nil"); + } + LUA_TSTRING | LUA_TNUMBER => { + lua_pushvalue(L, idx); + } + LUA_TBOOLEAN => { + if lua_toboolean(L, idx) == 0 { + lua_pushliteral(L, "false"); + } else { + lua_pushliteral(L, "true"); + } + } + _ => { + let tt = luaL_getmetafield(L, idx, cstr!("__name")); + let name = if tt == LUA_TSTRING { + lua_tostring(L, -1) + } else { + lua_typename(L, t) + }; + lua_pushfstring(L, cstr!("%s: %p"), name, lua_topointer(L, idx)); + if tt != LUA_TNIL { + lua_replace(L, -2); + } + } + }; + } else if lua_isstring(L, -1) == 0 { + luaL_error(L, cstr!("'__tostring' must return a string")); + } + lua_tolstring(L, -1, len) +} + +pub unsafe fn luaL_requiref( + L: *mut lua_State, + modname: *const c_char, + openf: lua_CFunction, + glb: c_int, +) { + luaL_checkstack(L, 3, cstr!("not enough stack slots available")); + luaL_getsubtable(L, LUA_REGISTRYINDEX, cstr!("_LOADED")); + if lua_getfield(L, -1, modname) == LUA_TNIL { + lua_pop(L, 1); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); + } + if glb != 0 { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } + lua_replace(L, -2); +} diff --git a/src/ffi/lua52/mod.rs b/src/ffi/lua52/mod.rs index a50765d..7ea8ef1 100644 --- a/src/ffi/lua52/mod.rs +++ b/src/ffi/lua52/mod.rs @@ -1,9 +1,11 @@ //! Low level bindings to Lua 5.2. -pub use self::lauxlib::*; -pub use self::lua::*; -pub use self::lualib::*; +pub use compat::*; +pub use lauxlib::*; +pub use lua::*; +pub use lualib::*; +pub mod compat; pub mod lauxlib; pub mod lua; pub mod lualib; diff --git a/src/ffi/lua53/compat.rs b/src/ffi/lua53/compat.rs new file mode 100644 index 0000000..7150b71 --- /dev/null +++ b/src/ffi/lua53/compat.rs @@ -0,0 +1,19 @@ +//! MLua compatibility layer for Lua 5.2 + +use std::os::raw::c_int; + +use super::lua::*; + +#[inline(always)] +pub unsafe fn lua_resume( + L: *mut lua_State, + from: *mut lua_State, + narg: c_int, + nres: *mut c_int, +) -> c_int { + let ret = lua_resume_(L, from, narg); + if (ret == LUA_OK || ret == LUA_YIELD) && !(nres.is_null()) { + *nres = lua_gettop(L); + } + ret +} diff --git a/src/ffi/lua53/mod.rs b/src/ffi/lua53/mod.rs index c5e07f2..13f107b 100644 --- a/src/ffi/lua53/mod.rs +++ b/src/ffi/lua53/mod.rs @@ -1,9 +1,11 @@ //! Low level bindings to Lua 5.3. -pub use self::lauxlib::*; -pub use self::lua::*; -pub use self::lualib::*; +pub use compat::*; +pub use lauxlib::*; +pub use lua::*; +pub use lualib::*; +pub mod compat; pub mod lauxlib; pub mod lua; pub mod lualib; diff --git a/src/ffi/lua54/mod.rs b/src/ffi/lua54/mod.rs index 96d61e6..2371e83 100644 --- a/src/ffi/lua54/mod.rs +++ b/src/ffi/lua54/mod.rs @@ -1,8 +1,8 @@ //! Low level bindings to Lua 5.4. -pub use self::lauxlib::*; -pub use self::lua::*; -pub use self::lualib::*; +pub use lauxlib::*; +pub use lua::*; +pub use lualib::*; pub mod lauxlib; pub mod lua; diff --git a/src/ffi/lualib.rs b/src/ffi/lualib.rs deleted file mode 100644 index ff50d85..0000000 --- a/src/ffi/lualib.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Contains definitions from `lualib.h`. - -#[cfg(feature = "lua54")] -pub use super::lua54::lualib::*; - -#[cfg(feature = "lua53")] -pub use super::lua53::lualib::*; - -#[cfg(feature = "lua52")] -pub use super::lua52::lualib::*; - -#[cfg(any(feature = "lua51", feature = "luajit"))] -pub use super::lua51::lualib::*; - -#[cfg(feature = "luau")] -pub use super::luau::lualib::*; diff --git a/src/ffi/luau/compat.rs b/src/ffi/luau/compat.rs new file mode 100644 index 0000000..eb3b7db --- /dev/null +++ b/src/ffi/luau/compat.rs @@ -0,0 +1,555 @@ +//! MLua compatibility layer for Roblox Luau. +//! +//! Based on github.com/keplerproject/lua-compat-5.3 + +use std::convert::TryInto; +use std::ffi::CStr; +use std::mem; +use std::os::raw::{c_char, c_int, c_void}; +use std::ptr; + +use super::lauxlib::*; +use super::lua::*; +use super::luacode::*; + +unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) { + while a < b { + lua_pushvalue(L, a); + lua_pushvalue(L, b); + lua_replace(L, a); + lua_replace(L, b); + a += 1; + b -= 1; + } +} + +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 + +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_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 + } + + lua_pushnil(L); // start 'next' loop + while lua_next(L, -2) != 0 { + // for each pair in table + if lua_type(L, -2) == LUA_TSTRING { + // ignore non-string keys + if lua_rawequal(L, objidx, -1) != 0 { + // found object? + lua_pop(L, 1); // remove value (but keep name) + return 1; + } else if compat53_findfield(L, objidx, level - 1) != 0 { + // try recursively + lua_remove(L, -2); // remove table (but keep name) + lua_pushliteral(L, "."); + lua_insert(L, -2); // place '.' between the two names + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); // remove value + } + return 0; // not found +} + +unsafe fn compat53_pushglobalfuncname( + L: *mut lua_State, + level: c_int, + ar: *mut lua_Debug, +) -> c_int { + let top = lua_gettop(L); + // 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 + lua_pop(L, 2); // remove pushed values + return 1; + } else { + lua_settop(L, top); // remove function and global table + return 0; + } +} + +#[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, + ); + } +} + +// +// lua ported functions +// + +pub unsafe fn lua_rotate(L: *mut lua_State, mut idx: c_int, mut n: c_int) { + idx = lua_absindex(L, idx); + let n_elems = lua_gettop(L) - idx + 1; + if n < 0 { + n += n_elems; + } + if n > 0 && n < n_elems { + luaL_checkstack(L, 2, cstr!("not enough stack slots available")); + n = n_elems - n; + compat53_reverse(L, idx, idx + n - 1); + compat53_reverse(L, idx + n, idx + n_elems - 1); + compat53_reverse(L, idx, idx + n_elems - 1); + } +} + +#[inline(always)] +pub unsafe fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int) { + let abs_to = lua_absindex(L, toidx); + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + lua_pushvalue(L, fromidx); + lua_replace(L, abs_to); +} + +#[inline(always)] +pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int { + if lua_type(L, idx) == LUA_TNUMBER { + let n = lua_tonumber(L, idx); + let i = lua_tointeger(L, idx); + if (n - i as lua_Number).abs() < lua_Number::EPSILON { + return 1; + } + } + 0 +} + +#[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_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer { + let mut ok = 0; + let n = lua_tonumberx(L, i, &mut ok); + let n_int = n as lua_Integer; + if ok != 0 && (n - n_int as lua_Number).abs() < lua_Number::EPSILON { + if !isnum.is_null() { + *isnum = 1; + } + return n_int; + } + if !isnum.is_null() { + *isnum = 0; + } + 0 +} + +#[inline(always)] +pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize { + lua_objlen(L, idx) +} + +#[inline(always)] +pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char { + if l == 0 { + lua_pushlstring_(L, cstr!(""), 0); + } else { + lua_pushlstring_(L, s, l); + } + lua_tostring(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char { + lua_pushstring_(L, s); + lua_tostring(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_geti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) -> c_int { + idx = lua_absindex(L, idx); + lua_pushinteger(L, n); + lua_gettable(L, idx) +} + +#[inline(always)] +pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int { + let n = n.try_into().expect("cannot convert index to lua_Integer"); + lua_rawgeti_(L, idx, n) +} + +#[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); + lua_pushlightuserdata(L, p as *mut c_void); + lua_rawget(L, abs_i) +} + +#[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"); + if lua_rawget(L, LUA_REGISTRYINDEX) != LUA_TTABLE { + return LUA_TNIL; + } + lua_pushvalue(L, idx); + lua_rawget(L, -2); + lua_remove(L, -2); + lua_type(L, -1) +} + +#[inline(always)] +pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) { + luaL_checkstack(L, 1, cstr!("not enough stack slots available")); + idx = lua_absindex(L, idx); + lua_pushinteger(L, n); + lua_insert(L, -2); + lua_settable(L, idx); +} + +#[inline(always)] +pub unsafe fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer) { + let n = n.try_into().expect("cannot convert index from lua_Integer"); + lua_rawseti_(L, idx, n) +} + +#[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); + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + lua_pushlightuserdata(L, p as *mut c_void); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + +#[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); + if lua_rawget(L, LUA_REGISTRYINDEX) != LUA_TTABLE { + 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); +} + +#[inline(always)] +pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) { + match lua_type(L, idx) { + LUA_TSTRING => { + lua_pushnumber(L, lua_objlen(L, idx) as lua_Number); + } + LUA_TTABLE => { + if luaL_callmeta(L, idx, cstr!("__len")) == 0 { + lua_pushnumber(L, lua_objlen(L, idx) as lua_Number); + } + } + LUA_TUSERDATA if luaL_callmeta(L, idx, cstr!("__len")) != 0 => {} + _ => { + luaL_error( + L, + cstr!("attempt to get length of a %s value"), + lua_typename(L, lua_type(L, idx)), + ); + } + } +} + +#[inline(always)] +pub unsafe fn lua_pushglobaltable(L: *mut lua_State) { + lua_pushvalue(L, LUA_GLOBALSINDEX); +} + +#[inline(always)] +pub unsafe fn lua_resume( + L: *mut lua_State, + from: *mut lua_State, + narg: c_int, + nres: *mut c_int, +) -> c_int { + let ret = lua_resume_(L, from, narg); + if (ret == LUA_OK || ret == LUA_YIELD) && !(nres.is_null()) { + *nres = lua_gettop(L); + } + ret +} + +// +// lauxlib ported functions +// + +#[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 { + if !msg.is_null() { + luaL_error(L, cstr!("stack overflow (%s)"), msg); + } else { + lua_pushliteral(L, "stack overflow"); + lua_error(L); + } + } +} + +#[inline(always)] +pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int { + if luaL_getmetafield_(L, obj, e) != 0 { + lua_type(L, -1) + } else { + LUA_TNIL + } +} + +#[inline(always)] +pub unsafe fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int { + if luaL_newmetatable_(L, tname) != 0 { + lua_pushstring(L, tname); + lua_setfield(L, -2, cstr!("__name")); + 1 + } else { + 0 + } +} + +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 { + extern "C" { + fn free(p: *mut c_void); + } + + 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_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_pushfstring( + L, + cstr!("attempt to load a text chunk (mode is '%s')"), + mode, + ); + return LUA_ERRSYNTAX; + } + } + + if chunk_is_text { + let data = luau_compile(data, size, ptr::null_mut(), &mut size); + let ok = luau_load(L, name, data, size, 0) == 0; + free(data as *mut c_void); + if !ok { + return LUA_ERRSYNTAX; + } + } else { + if 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()) +} + +#[inline(always)] +pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer { + let mut isnum = 0; + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + lua_len(L, idx); + let res = lua_tointegerx(L, -1, &mut isnum); + lua_pop(L, 1); + if isnum == 0 { + luaL_error(L, cstr!("object length is not an integer")); + } + res +} + +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); + match t { + LUA_TNIL => { + lua_pushliteral(L, "nil"); + } + LUA_TSTRING | LUA_TNUMBER => { + lua_pushvalue(L, idx); + } + LUA_TBOOLEAN => { + if lua_toboolean(L, idx) == 0 { + lua_pushliteral(L, "false"); + } else { + lua_pushliteral(L, "true"); + } + } + _ => { + let tt = luaL_getmetafield(L, idx, cstr!("__name")); + let name = if tt == LUA_TSTRING { + lua_tostring(L, -1) + } else { + lua_typename(L, t) + }; + lua_pushfstring(L, cstr!("%s: %p"), name, lua_topointer(L, idx)); + if tt != LUA_TNIL { + lua_replace(L, -2); + } + } + }; + } else if lua_isstring(L, -1) == 0 { + luaL_error(L, cstr!("'__tostring' must return a string")); + } + lua_tolstring(L, -1, len) +} + +#[inline(always)] +pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) { + luaL_checkstack(L, 1, cstr!("not enough stack slots")); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +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")); + lua_pushstring_(L, fname); + if lua_gettable(L, abs_i) == LUA_TTABLE { + return 1; + } + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring_(L, fname); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + 0 +} + +pub unsafe fn luaL_requiref( + L: *mut lua_State, + modname: *const c_char, + openf: lua_CFunction, + glb: c_int, +) { + luaL_checkstack(L, 3, cstr!("not enough stack slots available")); + luaL_getsubtable(L, LUA_REGISTRYINDEX, cstr!("_LOADED")); + if lua_getfield(L, -1, modname) == LUA_TNIL { + lua_pop(L, 1); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); + } + if glb != 0 { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } + lua_replace(L, -2); +} diff --git a/src/ffi/luau/lauxlib.rs b/src/ffi/luau/lauxlib.rs index fe7e6a8..2a10ed2 100644 --- a/src/ffi/luau/lauxlib.rs +++ b/src/ffi/luau/lauxlib.rs @@ -1,15 +1,11 @@ //! 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, + self, lua_CFunction, lua_Integer, lua_Number, lua_State, lua_Unsigned, LUA_REGISTRYINDEX, }; -use super::luacode; #[repr(C)] pub struct luaL_Reg { @@ -112,8 +108,8 @@ pub unsafe fn luaL_typename(L: *mut lua_State, i: c_int) -> *const c_char { } #[inline(always)] -pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) { - lua::lua_getfield_(L, LUA_REGISTRYINDEX, n); +pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) -> c_int { + lua::lua_getfield(L, LUA_REGISTRYINDEX, n) } #[inline(always)] @@ -130,59 +126,6 @@ pub unsafe fn luaL_unref(L: *mut lua_State, t: c_int, r#ref: c_int) { 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 // diff --git a/src/ffi/luau/lua.rs b/src/ffi/luau/lua.rs index 9c7e361..8638ee5 100644 --- a/src/ffi/luau/lua.rs +++ b/src/ffi/luau/lua.rs @@ -74,7 +74,6 @@ 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, ud: *mut c_void, ptr: *mut c_void, osize: usize, @@ -169,15 +168,12 @@ extern "C" { // // Get functions (Lua -> stack) // - #[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); - #[link_name = "lua_rawget"] - pub fn lua_rawget_(L: *mut lua_State, idx: c_int); + pub fn lua_gettable(L: *mut lua_State, idx: c_int) -> c_int; + pub fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int; + pub fn lua_rawgetfield(L: *mut lua_State, idx: c_int, k: *const c_char) -> c_int; + pub fn lua_rawget(L: *mut lua_State, idx: c_int) -> c_int; #[link_name = "lua_rawgeti"] - pub fn lua_rawgeti_(L: *mut lua_State, idx: c_int, n: c_int); + pub fn lua_rawgeti_(L: *mut lua_State, idx: c_int, n: c_int) -> 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); @@ -382,8 +378,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) -> c_int { + lua_getfield(L, LUA_GLOBALSINDEX, var) } #[inline(always)] diff --git a/src/ffi/luau/mod.rs b/src/ffi/luau/mod.rs index feec60d..e46093c 100644 --- a/src/ffi/luau/mod.rs +++ b/src/ffi/luau/mod.rs @@ -1,10 +1,12 @@ //! Low level bindings to Luau. -pub use self::lauxlib::*; -pub use self::lua::*; -pub use self::luacode::*; -pub use self::lualib::*; +pub use compat::*; +pub use lauxlib::*; +pub use lua::*; +pub use luacode::*; +pub use lualib::*; +pub mod compat; pub mod lauxlib; pub mod lua; pub mod luacode; diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 8382474..09164b9 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -2,9 +2,38 @@ #![allow(non_camel_case_types, non_snake_case, dead_code)] -pub use lauxlib::*; -pub use lua::*; -pub use lualib::*; +use std::os::raw::c_int; + +#[cfg(feature = "lua54")] +pub use lua54::*; + +#[cfg(feature = "lua53")] +pub use lua53::*; + +#[cfg(feature = "lua52")] +pub use lua52::*; + +#[cfg(any(feature = "lua51", feature = "luajit"))] +pub use lua51::*; + +#[cfg(feature = "luau")] +pub use luau::*; + +#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] +pub const LUA_MAX_UPVALUES: c_int = 255; + +#[cfg(any(feature = "lua51", all(feature = "luajit", not(feature = "vendored"))))] +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; + +// 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; // The minimum alignment guaranteed by the architecture. This value is used to // add fast paths for low alignment values. @@ -56,18 +85,6 @@ pub(crate) fn keep_lua_symbols() { } } -mod lauxlib; -mod lua; -mod lualib; - -#[cfg(any( - feature = "lua52", - feature = "lua51", - feature = "luajit", - feature = "luau" -))] -mod compat53; - #[cfg(feature = "lua54")] pub mod lua54; diff --git a/src/lua.rs b/src/lua.rs index 87a343d..90ca6d3 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -1481,16 +1481,22 @@ impl Lua { /// Resets thread (coroutine) and returns to the cache for later use. #[cfg(feature = "async")] #[cfg(any(feature = "lua54", all(feature = "luajit", feature = "vendored")))] - pub(crate) fn recycle_thread(&self, thread: &mut Thread) { - unsafe { - let extra = &mut *self.extra.get(); - let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index); - if extra.recycled_thread_cache.len() < extra.recycled_thread_cache.capacity() - && ffi::lua_resetthreadx(self.state, thread_state) == ffi::LUA_OK - { - extra.recycled_thread_cache.push(thread.0.index); - thread.0.index = 0; + pub(crate) unsafe fn recycle_thread(&self, thread: &mut Thread) { + let extra = &mut *self.extra.get(); + let thread_state = ffi::lua_tothread(extra.ref_thread, thread.0.index); + if extra.recycled_thread_cache.len() < extra.recycled_thread_cache.capacity() { + #[cfg(feature = "lua54")] + let status = ffi::lua_resetthread(thread_state); + #[cfg(feature = "lua54")] + if status != ffi::LUA_OK { + return; } + #[cfg(all(feature = "luajit", feature = "vendored"))] + ffi::lua_resetthread(self.state, thread_state); + #[cfg(feature = "luau")] + ffi::lua_resetthread(thread_state); + extra.recycled_thread_cache.push(thread.0.index); + thread.0.index = 0; } } diff --git a/src/thread.rs b/src/thread.rs index f4445a0..1086d81 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -192,10 +192,16 @@ impl<'lua> Thread<'lua> { lua.push_ref(&self.0); let thread_state = ffi::lua_tothread(lua.state, -1); - let ret = ffi::lua_resetthreadx(lua.state, thread_state); - if ret != ffi::LUA_OK { - return Err(pop_error(thread_state, ret)); + #[cfg(feature = "lua54")] + let status = ffi::lua_resetthread(thread_state); + #[cfg(feature = "lua54")] + if status != ffi::LUA_OK { + return Err(pop_error(thread_state, status)); } + #[cfg(all(feature = "luajit", feature = "vendored"))] + ffi::lua_resetthread(lua.state, thread_state); + #[cfg(feature = "luau")] + ffi::lua_resetthread(thread_state); lua.push_ref(&func.0); ffi::lua_xmove(lua.state, thread_state, 1); @@ -285,7 +291,9 @@ impl<'lua, R> AsyncThread<'lua, R> { impl<'lua, R> Drop for AsyncThread<'lua, R> { fn drop(&mut self) { if self.recycle { - self.thread.0.lua.recycle_thread(&mut self.thread); + unsafe { + self.thread.0.lua.recycle_thread(&mut self.thread); + } } } }