Initial Luau support
This commit is contained in:
parent
6dc127f4eb
commit
c322e028e2
|
@ -9,7 +9,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||||
rust: [stable]
|
rust: [stable]
|
||||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
|
@ -108,7 +108,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04, macos-latest, windows-latest]
|
os: [ubuntu-20.04, macos-latest, windows-latest]
|
||||||
rust: [stable, nightly]
|
rust: [stable, nightly]
|
||||||
lua: [lua54, lua53, lua52, lua51, luajit, luajit52]
|
lua: [lua54, lua53, lua52, lua51, luajit, luajit52, luau]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
|
@ -144,7 +144,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-20.04]
|
||||||
rust: [nightly]
|
rust: [nightly]
|
||||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
|
@ -228,7 +228,7 @@ jobs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
lua: [lua54, lua53, lua52, lua51, luajit]
|
lua: [lua54, lua53, lua52, lua51, luajit, luau]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
|
|
|
@ -34,7 +34,7 @@ lua52 = []
|
||||||
lua51 = []
|
lua51 = []
|
||||||
luajit = []
|
luajit = []
|
||||||
luajit52 = ["luajit"]
|
luajit52 = ["luajit"]
|
||||||
luau = ["luau-src"]
|
luau = ["luau0-src"]
|
||||||
vendored = ["lua-src", "luajit-src"]
|
vendored = ["lua-src", "luajit-src"]
|
||||||
module = ["mlua_derive"]
|
module = ["mlua_derive"]
|
||||||
async = ["futures-core", "futures-task", "futures-util"]
|
async = ["futures-core", "futures-task", "futures-util"]
|
||||||
|
@ -59,7 +59,7 @@ cc = { version = "1.0" }
|
||||||
pkg-config = { version = "0.3.17" }
|
pkg-config = { version = "0.3.17" }
|
||||||
lua-src = { version = ">= 540.0.0, < 550.0.0", optional = true }
|
lua-src = { version = ">= 540.0.0, < 550.0.0", optional = true }
|
||||||
luajit-src = { version = ">= 210.3.1, < 220.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]
|
[dev-dependencies]
|
||||||
rustyline = "9.0"
|
rustyline = "9.0"
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub fn probe_lua() -> Option<PathBuf> {
|
||||||
builder.build()
|
builder.build()
|
||||||
};
|
};
|
||||||
#[cfg(feature = "luau")]
|
#[cfg(feature = "luau")]
|
||||||
let artifacts = luau_src::Build::new().build();
|
let artifacts = luau0_src::Build::new().build();
|
||||||
|
|
||||||
#[cfg(not(feature = "module"))]
|
#[cfg(not(feature = "module"))]
|
||||||
artifacts.print_cargo_metadata();
|
artifacts.print_cargo_metadata();
|
||||||
|
|
|
@ -17,6 +17,9 @@ use super::lua52::*;
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
use super::lua51::*;
|
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) {
|
unsafe fn compat53_reverse(L: *mut lua_State, mut a: c_int, mut b: c_int) {
|
||||||
while a < b {
|
while a < b {
|
||||||
lua_pushvalue(L, a);
|
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_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
|
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 {
|
unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int {
|
||||||
let mut ar: lua_Debug = mem::zeroed();
|
let mut ar: lua_Debug = mem::zeroed();
|
||||||
let (mut li, mut le) = (1, 1);
|
let (mut li, mut le) = (1, 1);
|
||||||
|
@ -51,6 +55,27 @@ unsafe fn compat53_countlevels(L: *mut lua_State) -> c_int {
|
||||||
le - 1
|
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(
|
unsafe fn compat53_checkmode(
|
||||||
L: *mut lua_State,
|
L: *mut lua_State,
|
||||||
mode: *const c_char,
|
mode: *const c_char,
|
||||||
|
@ -81,7 +106,7 @@ unsafe fn compat53_checkmode(
|
||||||
LUA_OK
|
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 {
|
unsafe fn compat53_findfield(L: *mut lua_State, objidx: c_int, level: c_int) -> c_int {
|
||||||
if level == 0 || lua_istable(L, -1) == 0 {
|
if level == 0 || lua_istable(L, -1) == 0 {
|
||||||
return 0; // not found
|
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
|
return 0; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
unsafe fn compat53_pushglobalfuncname(L: *mut lua_State, ar: *mut lua_Debug) -> c_int {
|
unsafe fn compat53_pushglobalfuncname(
|
||||||
|
L: *mut lua_State,
|
||||||
|
level: c_int,
|
||||||
|
ar: *mut lua_Debug,
|
||||||
|
) -> c_int {
|
||||||
let top = lua_gettop(L);
|
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);
|
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||||
if compat53_findfield(L, top + 1, 2) != 0 {
|
if compat53_findfield(L, top + 1, 2) != 0 {
|
||||||
lua_copy(L, -1, top + 1); // move name to proper place
|
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"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) {
|
unsafe fn compat53_pushfuncname(L: *mut lua_State, ar: *mut lua_Debug) {
|
||||||
if *(*ar).namewhat != b'\0' as c_char {
|
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?
|
// main?
|
||||||
lua_pushliteral(L, "main chunk");
|
lua_pushliteral(L, "main chunk");
|
||||||
} else if *(*ar).what == b'C' as c_char {
|
} 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_pushfstring(L, cstr!("function '%s'"), lua_tostring(L, -1));
|
||||||
lua_remove(L, -2); // remove name
|
lua_remove(L, -2); // remove name
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,22 +245,22 @@ pub unsafe fn lua_absindex(L: *mut lua_State, mut idx: c_int) -> c_int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison and arithmetic functions
|
// 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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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#"
|
static COMPAT53_ARITH_CODE: &str = r#"
|
||||||
local op,a,b = ...
|
local op,a,b = ...
|
||||||
if op == 0 then return a+b
|
if op == 0 then return a+b
|
||||||
|
@ -212,7 +273,7 @@ elseif op == 6 then return -a
|
||||||
end
|
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) {
|
pub unsafe fn lua_arith(L: *mut lua_State, op: c_int) {
|
||||||
#[allow(clippy::manual_range_contains)]
|
#[allow(clippy::manual_range_contains)]
|
||||||
if op < LUA_OPADD || op > LUA_OPUNM {
|
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)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int) {
|
pub unsafe fn lua_copy(L: *mut lua_State, fromidx: c_int, toidx: c_int) {
|
||||||
let abs_to = lua_absindex(L, toidx);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "lua52",
|
||||||
|
feature = "lua51",
|
||||||
|
feature = "luajit",
|
||||||
|
feature = "luau"
|
||||||
|
))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
|
pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
|
||||||
lua_tointegerx(L, i, ptr::null_mut())
|
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
|
// Implemented for Lua 5.2 as well
|
||||||
// See https://github.com/keplerproject/lua-compat-5.3/issues/40
|
// See https://github.com/keplerproject/lua-compat-5.3/issues/40
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "lua52",
|
||||||
|
feature = "lua51",
|
||||||
|
feature = "luajit",
|
||||||
|
feature = "luau"
|
||||||
|
))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer {
|
pub unsafe fn lua_tointegerx(L: *mut lua_State, i: c_int, isnum: *mut c_int) -> lua_Integer {
|
||||||
let mut ok = 0;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize {
|
pub unsafe fn lua_rawlen(L: *mut lua_State, idx: c_int) -> usize {
|
||||||
lua_objlen(L, idx)
|
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;
|
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;
|
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;
|
pub const LUA_OPLE: c_int = 2;
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_compare(L: *mut lua_State, mut idx1: c_int, mut idx2: c_int, op: c_int) -> c_int {
|
pub unsafe fn lua_compare(L: *mut lua_State, mut idx1: c_int, mut idx2: c_int, op: c_int) -> c_int {
|
||||||
match op {
|
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)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char {
|
pub unsafe fn lua_pushlstring(L: *mut lua_State, s: *const c_char, l: usize) -> *const c_char {
|
||||||
if l == 0 {
|
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)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char {
|
pub unsafe fn lua_pushstring(L: *mut lua_State, s: *const c_char) -> *const c_char {
|
||||||
lua_pushstring_(L, s);
|
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)
|
lua_type(L, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_rawgetp(L: *mut lua_State, idx: c_int, p: *const c_void) -> c_int {
|
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);
|
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)
|
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")]
|
#[cfg(feature = "lua52")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_getuservalue(L: *mut lua_State, idx: c_int) -> c_int {
|
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)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void) {
|
pub unsafe fn lua_rawsetp(L: *mut lua_State, idx: c_int, p: *const c_void) {
|
||||||
let abs_i = lua_absindex(L, idx);
|
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);
|
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)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_dump(
|
pub unsafe fn lua_dump(
|
||||||
L: *mut lua_State,
|
L: *mut lua_State,
|
||||||
|
@ -476,7 +593,7 @@ pub unsafe fn lua_dump(
|
||||||
lua_dump_(L, writer, data)
|
lua_dump_(L, writer, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) {
|
pub unsafe fn lua_len(L: *mut lua_State, idx: c_int) {
|
||||||
match lua_type(L, idx) {
|
match lua_type(L, idx) {
|
||||||
|
@ -565,7 +682,7 @@ pub unsafe fn lua_getextraspace(L: *mut lua_State) -> *mut c_void {
|
||||||
return _ptr;
|
return _ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
|
pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
|
||||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||||
|
@ -575,7 +692,7 @@ pub unsafe fn lua_pushglobaltable(L: *mut lua_State) {
|
||||||
// lauxlib ported functions
|
// lauxlib ported functions
|
||||||
//
|
//
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char) {
|
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 lua_checkstack(L, sz + LUA_MINSTACK) == 0 {
|
||||||
|
@ -628,7 +745,7 @@ pub unsafe fn luaL_loadbufferx(
|
||||||
luaL_loadbuffer(L, buff, sz, name)
|
luaL_loadbuffer(L, buff, sz, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer {
|
pub unsafe fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer {
|
||||||
let mut isnum = 0;
|
let mut isnum = 0;
|
||||||
|
@ -682,6 +799,46 @@ pub unsafe fn luaL_traceback(
|
||||||
lua_concat(L, lua_gettop(L) - top);
|
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 {
|
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 {
|
if luaL_callmeta(L, idx, cstr!("__tostring")) == 0 {
|
||||||
let t = lua_type(L, idx);
|
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)
|
lua_tolstring(L, -1, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) {
|
pub unsafe fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char) {
|
||||||
luaL_checkstack(L, 1, cstr!("not enough stack slots"));
|
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);
|
lua_setmetatable(L, -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn luaL_testudata(L: *mut lua_State, i: c_int, tname: *const c_char) -> *mut c_void {
|
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);
|
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
|
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 {
|
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);
|
let abs_i = lua_absindex(L, idx);
|
||||||
luaL_checkstack(L, 3, cstr!("not enough stack slots"));
|
luaL_checkstack(L, 3, cstr!("not enough stack slots"));
|
||||||
|
@ -791,7 +948,7 @@ pub unsafe fn luaL_requiref(
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
lua_pushcfunction(L, openf);
|
lua_pushcfunction(L, openf);
|
||||||
lua_pushstring(L, modname);
|
lua_pushstring(L, modname);
|
||||||
#[cfg(any(feature = "lua52", feature = "lua51"))]
|
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luau"))]
|
||||||
{
|
{
|
||||||
lua_call(L, 1, 1);
|
lua_call(L, 1, 1);
|
||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
|
@ -803,7 +960,7 @@ pub unsafe fn luaL_requiref(
|
||||||
lua_getfield(L, -1, modname);
|
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_pushvalue(L, -1);
|
||||||
lua_setglobal(L, modname);
|
lua_setglobal(L, modname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ pub use super::lua52::lauxlib::*;
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
pub use super::lua51::lauxlib::*;
|
pub use super::lua51::lauxlib::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "luau")]
|
||||||
|
pub use super::luau::lauxlib::*;
|
||||||
|
|
||||||
#[cfg(feature = "lua52")]
|
#[cfg(feature = "lua52")]
|
||||||
pub use super::compat53::{luaL_getmetafield, luaL_newmetatable, luaL_requiref, luaL_tolstring};
|
pub use super::compat53::{luaL_getmetafield, luaL_newmetatable, luaL_requiref, luaL_tolstring};
|
||||||
|
|
||||||
|
@ -24,6 +27,12 @@ pub use super::compat53::{
|
||||||
luaL_tolstring, luaL_traceback,
|
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.
|
// I believe `luaL_traceback` < 5.4 requires this much free stack to not error.
|
||||||
// 5.4 uses `luaL_Buffer`
|
// 5.4 uses `luaL_Buffer`
|
||||||
pub const LUA_TRACEBACK_STACK: c_int = 11;
|
pub const LUA_TRACEBACK_STACK: c_int = 11;
|
||||||
|
|
|
@ -14,6 +14,9 @@ pub use super::lua52::lua::*;
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
pub use super::lua51::lua::*;
|
pub use super::lua51::lua::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "luau")]
|
||||||
|
pub use super::luau::lua::*;
|
||||||
|
|
||||||
#[cfg(feature = "lua52")]
|
#[cfg(feature = "lua52")]
|
||||||
pub use super::compat53::{
|
pub use super::compat53::{
|
||||||
lua_dump, lua_getextraspace, lua_getfield, lua_getglobal, lua_geti, lua_gettable,
|
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,
|
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",))]
|
#[cfg(any(feature = "lua52", feature = "lua53", feature = "lua54",))]
|
||||||
pub const LUA_MAX_UPVALUES: c_int = 255;
|
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"))]
|
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||||
pub const LUA_MAX_UPVALUES: c_int = 120;
|
pub const LUA_MAX_UPVALUES: c_int = 120;
|
||||||
|
|
||||||
|
#[cfg(feature = "luau")]
|
||||||
|
pub const LUA_MAX_UPVALUES: c_int = 200;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Lua 5.4 compatibility layer
|
// Lua 5.4 compatibility layer
|
||||||
//
|
//
|
||||||
|
@ -48,7 +62,8 @@ pub const LUA_MAX_UPVALUES: c_int = 120;
|
||||||
feature = "lua53",
|
feature = "lua53",
|
||||||
feature = "lua52",
|
feature = "lua52",
|
||||||
feature = "lua51",
|
feature = "lua51",
|
||||||
feature = "luajit"
|
feature = "luajit",
|
||||||
|
feature = "luau"
|
||||||
))]
|
))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_resume(
|
pub unsafe fn lua_resume(
|
||||||
|
@ -62,22 +77,32 @@ pub unsafe fn lua_resume(
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
let ret = lua_resume_(L, narg);
|
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);
|
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);
|
*nres = lua_gettop(L);
|
||||||
}
|
}
|
||||||
ret
|
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 {
|
pub unsafe fn lua_resetthreadx(L: *mut lua_State, th: *mut lua_State) -> c_int {
|
||||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||||
{
|
{
|
||||||
lua_resetthread(L, th);
|
lua_resetthread(L, th);
|
||||||
LUA_OK
|
LUA_OK
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "luau")]
|
||||||
|
{
|
||||||
|
let _ = L;
|
||||||
|
lua_resetthread(th);
|
||||||
|
LUA_OK
|
||||||
|
}
|
||||||
#[cfg(feature = "lua54")]
|
#[cfg(feature = "lua54")]
|
||||||
{
|
{
|
||||||
let _ = L;
|
let _ = L;
|
||||||
|
|
|
@ -11,3 +11,6 @@ pub use super::lua52::lualib::*;
|
||||||
|
|
||||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
pub use super::lua51::lualib::*;
|
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_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;
|
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.
|
/// Type for memory-allocation functions.
|
||||||
pub type lua_Alloc = unsafe extern "C" fn(
|
pub type lua_Alloc = unsafe extern "C" fn(
|
||||||
L: *mut lua_State,
|
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_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_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_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_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_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_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_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_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_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_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;
|
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_pushinteger(L: *mut lua_State, n: lua_Integer);
|
||||||
pub fn lua_pushunsigned(L: *mut lua_State, n: lua_Unsigned);
|
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_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);
|
#[link_name = "lua_pushlstring"]
|
||||||
pub fn lua_pushstring(L: *mut lua_State, s: *const c_char);
|
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
|
// lua_pushvfstring
|
||||||
#[link_name = "lua_pushfstringL"]
|
#[link_name = "lua_pushfstringL"]
|
||||||
pub fn lua_pushfstring(L: *mut lua_State, fmt: *const c_char, ...) -> *const c_char;
|
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)
|
// Get functions (Lua -> stack)
|
||||||
//
|
//
|
||||||
pub fn lua_gettable(L: *mut lua_State, idx: c_int);
|
#[link_name = "lua_gettable"]
|
||||||
pub fn lua_getfield(L: *mut lua_State, idx: c_int, k: *const c_char);
|
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_rawgetfield(L: *mut lua_State, idx: c_int, k: *const c_char);
|
||||||
pub fn lua_rawget(L: *mut lua_State, idx: c_int);
|
#[link_name = "lua_rawget"]
|
||||||
pub fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: c_int);
|
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_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);
|
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_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_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_getmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
|
||||||
pub fn lua_getfenv(L: *mut lua_State, idx: 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_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_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_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_setmetatable(L: *mut lua_State, objindex: c_int) -> c_int;
|
||||||
pub fn lua_setfenv(L: *mut lua_State, idx: 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_yield(L: *mut lua_State, nresults: c_int) -> c_int;
|
||||||
pub fn lua_break(L: *mut lua_State) -> 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_resumeerror(L: *mut lua_State, from: *mut lua_State) -> c_int;
|
||||||
pub fn lua_status(L: *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;
|
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_next(L: *mut lua_State, idx: c_int) -> c_int;
|
||||||
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
pub fn lua_concat(L: *mut lua_State, n: c_int);
|
||||||
// TODO: lua_encodepointer, lua_clock
|
// 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)
|
// Some useful macros (implemented as Rust functions)
|
||||||
//
|
//
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number {
|
pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number {
|
||||||
lua_tonumberx(L, i, ptr::null_mut())
|
lua_tonumberx(L, i, ptr::null_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer {
|
pub unsafe fn lua_tointeger_(L: *mut lua_State, i: c_int) -> lua_Integer {
|
||||||
lua_tointegerx(L, i, ptr::null_mut())
|
lua_tointegerx_(L, i, ptr::null_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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) {
|
pub unsafe fn lua_pushliteral(L: *mut lua_State, s: &'static str) {
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
let c_str = CString::new(s).unwrap();
|
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)
|
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,
|
L: *mut lua_State,
|
||||||
f: lua_CFunction,
|
f: lua_CFunction,
|
||||||
debugname: *const c_char,
|
debugname: *const c_char,
|
||||||
|
@ -361,8 +382,8 @@ pub unsafe fn lua_setglobal(L: *mut lua_State, var: *const c_char) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_getglobal(L: *mut lua_State, var: *const c_char) {
|
pub unsafe fn lua_getglobal_(L: *mut lua_State, var: *const c_char) {
|
||||||
lua_getfield(L, LUA_GLOBALSINDEX, var)
|
lua_getfield_(L, LUA_GLOBALSINDEX, var)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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`.
|
//! 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::{
|
use super::lua::lua_State;
|
||||||
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
|
|
||||||
//
|
|
||||||
|
|
||||||
pub const LUA_COLIBNAME: &str = "coroutine";
|
pub const LUA_COLIBNAME: &str = "coroutine";
|
||||||
pub const LUA_TABLIBNAME: &str = "table";
|
pub const LUA_TABLIBNAME: &str = "table";
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
//! Low level bindings to Luau.
|
//! Low level bindings to Luau.
|
||||||
|
|
||||||
|
pub use self::lauxlib::*;
|
||||||
pub use self::lua::*;
|
pub use self::lua::*;
|
||||||
|
pub use self::luacode::*;
|
||||||
pub use self::lualib::*;
|
pub use self::lualib::*;
|
||||||
|
|
||||||
|
pub mod lauxlib;
|
||||||
pub mod lua;
|
pub mod lua;
|
||||||
|
pub mod luacode;
|
||||||
pub mod lualib;
|
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
|
// Hack to avoid stripping a few unused Lua symbols that could be imported
|
||||||
// by C modules in unsafe mode
|
// by C modules in unsafe mode
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub(crate) fn keep_lua_symbols() {
|
pub(crate) fn keep_lua_symbols() {
|
||||||
let mut symbols: Vec<*const extern "C" fn()> = Vec::new();
|
let mut symbols: Vec<*const extern "C" fn()> = Vec::new();
|
||||||
symbols.push(lua_atpanic as _);
|
symbols.push(lua_atpanic as _);
|
||||||
|
@ -59,14 +60,25 @@ mod lauxlib;
|
||||||
mod lua;
|
mod lua;
|
||||||
mod lualib;
|
mod lualib;
|
||||||
|
|
||||||
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
|
#[cfg(any(
|
||||||
|
feature = "lua52",
|
||||||
|
feature = "lua51",
|
||||||
|
feature = "luajit",
|
||||||
|
feature = "luau"
|
||||||
|
))]
|
||||||
mod compat53;
|
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"))]
|
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||||
pub mod lua51;
|
pub mod lua51;
|
||||||
#[cfg(feature = "lua52")]
|
|
||||||
pub mod lua52;
|
#[cfg(feature = "luau")]
|
||||||
#[cfg(feature = "lua53")]
|
pub mod luau;
|
||||||
pub mod lua53;
|
|
||||||
#[cfg(feature = "lua54")]
|
|
||||||
pub mod lua54;
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::os::raw::{c_int, c_void};
|
use std::os::raw::c_int;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
|
@ -214,7 +213,11 @@ impl<'lua> Function<'lua> {
|
||||||
///
|
///
|
||||||
/// If `strip` is true, the binary representation may not include all debug information
|
/// If `strip` is true, the binary representation may not include all debug information
|
||||||
/// about the function, to save space.
|
/// about the function, to save space.
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub fn dump(&self, strip: bool) -> Vec<u8> {
|
pub fn dump(&self, strip: bool) -> Vec<u8> {
|
||||||
|
use std::os::raw::c_void;
|
||||||
|
use std::slice;
|
||||||
|
|
||||||
unsafe extern "C" fn writer(
|
unsafe extern "C" fn writer(
|
||||||
_state: *mut ffi::lua_State,
|
_state: *mut ffi::lua_State,
|
||||||
buf: *const c_void,
|
buf: *const c_void,
|
||||||
|
|
|
@ -85,6 +85,7 @@ mod conversion;
|
||||||
mod error;
|
mod error;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
mod function;
|
mod function;
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
mod hook;
|
mod hook;
|
||||||
mod lua;
|
mod lua;
|
||||||
mod multi;
|
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::error::{Error, ExternalError, ExternalResult, Result};
|
||||||
pub use crate::function::Function;
|
pub use crate::function::Function;
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack, HookTriggers};
|
pub use crate::hook::{Debug, DebugEvent, DebugNames, DebugSource, DebugStack, HookTriggers};
|
||||||
pub use crate::lua::{AsChunk, Chunk, ChunkMode, GCMode, Lua, LuaOptions};
|
pub use crate::lua::{AsChunk, Chunk, ChunkMode, GCMode, Lua, LuaOptions};
|
||||||
pub use crate::multi::Variadic;
|
pub use crate::multi::Variadic;
|
||||||
|
|
125
src/lua.rs
125
src/lua.rs
|
@ -14,6 +14,7 @@ use rustc_hash::FxHashMap;
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
use crate::function::Function;
|
use crate::function::Function;
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
use crate::hook::{Debug, HookTriggers};
|
use crate::hook::{Debug, HookTriggers};
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use crate::stdlib::StdLib;
|
use crate::stdlib::StdLib;
|
||||||
|
@ -21,8 +22,8 @@ use crate::string::String;
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
use crate::thread::Thread;
|
use crate::thread::Thread;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
Callback, CallbackUpvalue, DestructedUserdataMT, HookCallback, Integer, LightUserData, LuaRef,
|
Callback, CallbackUpvalue, DestructedUserdataMT, /*HookCallback,*/ Integer, LightUserData,
|
||||||
MaybeSend, Number, RegistryKey,
|
LuaRef, MaybeSend, Number, RegistryKey,
|
||||||
};
|
};
|
||||||
use crate::userdata::{
|
use crate::userdata::{
|
||||||
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
||||||
|
@ -35,6 +36,9 @@ use crate::util::{
|
||||||
};
|
};
|
||||||
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
use crate::value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
|
use crate::types::HookCallback;
|
||||||
|
|
||||||
#[cfg(not(feature = "lua54"))]
|
#[cfg(not(feature = "lua54"))]
|
||||||
use crate::util::push_userdata;
|
use crate::util::push_userdata;
|
||||||
#[cfg(feature = "lua54")]
|
#[cfg(feature = "lua54")]
|
||||||
|
@ -103,6 +107,7 @@ struct ExtraData {
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
ref_waker_idx: c_int,
|
ref_waker_idx: c_int,
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
hook_callback: Option<HookCallback>,
|
hook_callback: Option<HookCallback>,
|
||||||
#[cfg(feature = "lua54")]
|
#[cfg(feature = "lua54")]
|
||||||
warn_callback: Option<WarnCallback>,
|
warn_callback: Option<WarnCallback>,
|
||||||
|
@ -310,6 +315,7 @@ impl Lua {
|
||||||
|
|
||||||
let mut lua = unsafe { Self::inner_new(libs, options) };
|
let mut lua = unsafe { Self::inner_new(libs, options) };
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
if libs.contains(StdLib::PACKAGE) {
|
if libs.contains(StdLib::PACKAGE) {
|
||||||
mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
|
mlua_expect!(lua.disable_c_modules(), "Error during disabling C modules");
|
||||||
}
|
}
|
||||||
|
@ -328,12 +334,16 @@ impl Lua {
|
||||||
///
|
///
|
||||||
/// [`StdLib`]: crate::StdLib
|
/// [`StdLib`]: crate::StdLib
|
||||||
pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
|
pub unsafe fn unsafe_new_with(libs: StdLib, options: LuaOptions) -> Lua {
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
ffi::keep_lua_symbols();
|
ffi::keep_lua_symbols();
|
||||||
Self::inner_new(libs, options)
|
Self::inner_new(libs, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn inner_new(libs: StdLib, options: LuaOptions) -> Lua {
|
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(
|
unsafe extern "C" fn allocator(
|
||||||
extra_data: *mut c_void,
|
extra_data: *mut c_void,
|
||||||
ptr: *mut c_void,
|
ptr: *mut c_void,
|
||||||
|
@ -398,9 +408,14 @@ impl Lua {
|
||||||
|
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
let state = ffi::lua_newstate(allocator, mem_info as *mut c_void);
|
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();
|
let state = ffi::luaL_newstate();
|
||||||
|
|
||||||
|
// #[cfg(feature = "luau")]
|
||||||
|
// {
|
||||||
|
// ffi::luaL_sandbox(state);
|
||||||
|
// }
|
||||||
|
|
||||||
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
|
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
|
|
||||||
|
@ -427,7 +442,7 @@ impl Lua {
|
||||||
|
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
ffi::lua_rawgeti(lua.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
|
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_pushvalue(lua.state, ffi::LUA_GLOBALSINDEX);
|
||||||
|
|
||||||
ffi::lua_pushcfunction(lua.state, safe_pcall);
|
ffi::lua_pushcfunction(lua.state, safe_pcall);
|
||||||
|
@ -447,6 +462,9 @@ impl Lua {
|
||||||
extra.recycled_thread_cache = Vec::with_capacity(options.thread_cache_size);
|
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
|
lua
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,6 +552,7 @@ impl Lua {
|
||||||
recycled_thread_cache: Vec::new(),
|
recycled_thread_cache: Vec::new(),
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
ref_waker_idx,
|
ref_waker_idx,
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
hook_callback: None,
|
hook_callback: None,
|
||||||
#[cfg(feature = "lua54")]
|
#[cfg(feature = "lua54")]
|
||||||
warn_callback: None,
|
warn_callback: None,
|
||||||
|
@ -600,9 +619,12 @@ impl Lua {
|
||||||
|
|
||||||
// If `package` library loaded into a safe lua state then disable C modules
|
// If `package` library loaded into a safe lua state then disable C modules
|
||||||
let extra = unsafe { &mut *self.extra.get() };
|
let extra = unsafe { &mut *self.extra.get() };
|
||||||
let curr_libs = extra.libs;
|
#[cfg(not(feature = "luau"))]
|
||||||
if self.safe && (curr_libs ^ (curr_libs | libs)).contains(StdLib::PACKAGE) {
|
{
|
||||||
mlua_expect!(self.disable_c_modules(), "Error during disabling C modules");
|
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;
|
extra.libs |= libs;
|
||||||
|
|
||||||
|
@ -795,6 +817,7 @@ impl Lua {
|
||||||
///
|
///
|
||||||
/// [`HookTriggers`]: crate::HookTriggers
|
/// [`HookTriggers`]: crate::HookTriggers
|
||||||
/// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
|
/// [`HookTriggers.every_nth_instruction`]: crate::HookTriggers::every_nth_instruction
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
|
pub fn set_hook<F>(&self, triggers: HookTriggers, callback: F) -> Result<()>
|
||||||
where
|
where
|
||||||
F: 'static + MaybeSend + FnMut(&Lua, Debug) -> Result<()>,
|
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
|
/// Remove any hook previously set by `set_hook`. This function has no effect if a hook was not
|
||||||
/// previously set.
|
/// previously set.
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub fn remove_hook(&self) {
|
pub fn remove_hook(&self) {
|
||||||
// If main_state is not available, then sethook wasn't called.
|
// If main_state is not available, then sethook wasn't called.
|
||||||
let state = match self.main_state {
|
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).
|
/// function that has called level `n` (except for tail calls, which do not count in the stack).
|
||||||
///
|
///
|
||||||
/// [`Debug`]: crate::hook::Debug
|
/// [`Debug`]: crate::hook::Debug
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
|
pub fn inspect_stack(&self, level: usize) -> Option<Debug> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ar: ffi::lua_Debug = mem::zeroed();
|
let mut ar: ffi::lua_Debug = mem::zeroed();
|
||||||
|
@ -961,7 +986,12 @@ impl Lua {
|
||||||
/// Returns true if the garbage collector is currently running automatically.
|
/// Returns true if the garbage collector is currently running automatically.
|
||||||
///
|
///
|
||||||
/// Requires `feature = "lua54/lua53/lua52"`
|
/// 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 {
|
pub fn gc_is_running(&self) -> bool {
|
||||||
let state = self.main_state.unwrap_or(self.state);
|
let state = self.main_state.unwrap_or(self.state);
|
||||||
unsafe { ffi::lua_gc(state, ffi::LUA_GCISRUNNING, 0) != 0 }
|
unsafe { ffi::lua_gc(state, ffi::LUA_GCISRUNNING, 0) != 0 }
|
||||||
|
@ -1018,6 +1048,7 @@ impl Lua {
|
||||||
/// [documentation][lua_doc].
|
/// [documentation][lua_doc].
|
||||||
///
|
///
|
||||||
/// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#2.5
|
/// [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 {
|
pub fn gc_set_pause(&self, pause: c_int) -> c_int {
|
||||||
let state = self.main_state.unwrap_or(self.state);
|
let state = self.main_state.unwrap_or(self.state);
|
||||||
unsafe { ffi::lua_gc(state, ffi::LUA_GCSETPAUSE, pause) }
|
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].
|
/// 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
|
/// [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 {
|
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);
|
let state = self.main_state.unwrap_or(self.state);
|
||||||
|
|
||||||
|
@ -1138,6 +1170,7 @@ impl Lua {
|
||||||
}
|
}
|
||||||
Some(ChunkMode::Binary) => cstr!("b"),
|
Some(ChunkMode::Binary) => cstr!("b"),
|
||||||
Some(ChunkMode::Text) => cstr!("t"),
|
Some(ChunkMode::Text) => cstr!("t"),
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
None if source.starts_with(ffi::LUA_SIGNATURE) && self.safe => {
|
None if source.starts_with(ffi::LUA_SIGNATURE) && self.safe => {
|
||||||
return Err(Error::SafetyError(
|
return Err(Error::SafetyError(
|
||||||
"binary chunks are disabled in safe mode".to_string(),
|
"binary chunks are disabled in safe mode".to_string(),
|
||||||
|
@ -1158,7 +1191,7 @@ impl Lua {
|
||||||
self.push_value(env)?;
|
self.push_value(env)?;
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
ffi::lua_setupvalue(self.state, -2, 1);
|
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);
|
ffi::lua_setfenv(self.state, -2);
|
||||||
}
|
}
|
||||||
Ok(Function(self.pop_ref()))
|
Ok(Function(self.pop_ref()))
|
||||||
|
@ -1488,7 +1521,7 @@ impl Lua {
|
||||||
assert_stack(self.state, 1);
|
assert_stack(self.state, 1);
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
|
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);
|
ffi::lua_pushvalue(self.state, ffi::LUA_GLOBALSINDEX);
|
||||||
Table(self.pop_ref())
|
Table(self.pop_ref())
|
||||||
}
|
}
|
||||||
|
@ -2329,7 +2362,12 @@ impl Lua {
|
||||||
where
|
where
|
||||||
'lua: 'callback,
|
'lua: 'callback,
|
||||||
{
|
{
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
#[cfg(any(
|
||||||
|
feature = "lua54",
|
||||||
|
feature = "lua53",
|
||||||
|
feature = "lua52",
|
||||||
|
feature = "luau"
|
||||||
|
))]
|
||||||
unsafe {
|
unsafe {
|
||||||
let libs = (*self.extra.get()).libs;
|
let libs = (*self.extra.get()).libs;
|
||||||
if !libs.contains(StdLib::COROUTINE) {
|
if !libs.contains(StdLib::COROUTINE) {
|
||||||
|
@ -2551,6 +2589,7 @@ impl Lua {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
fn disable_c_modules(&self) -> Result<()> {
|
fn disable_c_modules(&self) -> Result<()> {
|
||||||
let package: Table = self.globals().get("package")?;
|
let package: Table = self.globals().get("package")?;
|
||||||
|
|
||||||
|
@ -2577,6 +2616,42 @@ impl Lua {
|
||||||
Ok(())
|
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> {
|
pub(crate) unsafe fn make_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
|
||||||
let _sg = StackGuard::new(state);
|
let _sg = StackGuard::new(state);
|
||||||
assert_stack(state, 1);
|
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
|
// For source code, first try interpreting the lua as an expression by adding
|
||||||
// "return", then as a statement. This is the same thing the
|
// "return", then as a statement. This is the same thing the
|
||||||
// actual lua repl does.
|
// actual lua repl does.
|
||||||
if self.source.starts_with(ffi::LUA_SIGNATURE) {
|
if self.source[0] < b'\n' {
|
||||||
self.call(())
|
self.call(())
|
||||||
} else if let Ok(function) = self.lua.load_chunk(
|
} else if let Ok(function) = self.lua.load_chunk(
|
||||||
&self.expression_source(),
|
&self.expression_source(),
|
||||||
|
@ -2768,7 +2843,7 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
|
||||||
'lua: 'fut,
|
'lua: 'fut,
|
||||||
R: FromLuaMulti<'lua> + 'fut,
|
R: FromLuaMulti<'lua> + 'fut,
|
||||||
{
|
{
|
||||||
if self.source.starts_with(ffi::LUA_SIGNATURE) {
|
if self.source[0] < b'\n' {
|
||||||
self.call_async(())
|
self.call_async(())
|
||||||
} else if let Ok(function) = self.lua.load_chunk(
|
} else if let Ok(function) = self.lua.load_chunk(
|
||||||
&self.expression_source(),
|
&self.expression_source(),
|
||||||
|
@ -2886,9 +2961,9 @@ where
|
||||||
let prealloc_failure = match extra.wrapped_failures_cache.pop() {
|
let prealloc_failure = match extra.wrapped_failures_cache.pop() {
|
||||||
Some(index) => PreallocatedFailure::Cached(index),
|
Some(index) => PreallocatedFailure::Cached(index),
|
||||||
None => {
|
None => {
|
||||||
let ud = ffi::lua_newuserdata(state, mem::size_of::<WrappedFailure>());
|
let ud = WrappedFailure::new_userdata(state);
|
||||||
ffi::lua_rotate(state, 1, 1);
|
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")]
|
#[cfg(feature = "luajit")]
|
||||||
let _gc_guard = GcGuard::new(state);
|
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) {
|
if libs.contains(StdLib::COROUTINE) {
|
||||||
requiref(state, ffi::LUA_COLIBNAME, ffi::luaopen_coroutine, 1)?;
|
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);
|
ffi::lua_pop(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
if libs.contains(StdLib::IO) {
|
if libs.contains(StdLib::IO) {
|
||||||
requiref(state, ffi::LUA_IOLIBNAME, ffi::luaopen_io, 1)?;
|
requiref(state, ffi::LUA_IOLIBNAME, ffi::luaopen_io, 1)?;
|
||||||
ffi::lua_pop(state, 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);
|
ffi::lua_pop(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "luau"))]
|
||||||
{
|
{
|
||||||
if libs.contains(StdLib::UTF8) {
|
if libs.contains(StdLib::UTF8) {
|
||||||
requiref(state, ffi::LUA_UTF8LIBNAME, ffi::luaopen_utf8, 1)?;
|
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) {
|
if libs.contains(StdLib::BIT) {
|
||||||
requiref(state, ffi::LUA_BITLIBNAME, ffi::luaopen_bit32, 1)?;
|
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);
|
ffi::lua_pop(state, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
if libs.contains(StdLib::PACKAGE) {
|
if libs.contains(StdLib::PACKAGE) {
|
||||||
requiref(state, ffi::LUA_LOADLIBNAME, ffi::luaopen_package, 1)?;
|
requiref(state, ffi::LUA_LOADLIBNAME, ffi::luaopen_package, 1)?;
|
||||||
ffi::lua_pop(state, 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// We move `extra` (`MutexGuard`) here to correctly drop it if panic
|
|
||||||
unsafe fn ref_stack_pop(extra: &mut ExtraData) -> c_int {
|
unsafe fn ref_stack_pop(extra: &mut ExtraData) -> c_int {
|
||||||
if let Some(free) = extra.ref_free.pop() {
|
if let Some(free) = extra.ref_free.pop() {
|
||||||
ffi::lua_replace(extra.ref_thread, free);
|
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)));
|
.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)
|
fn add_async_meta_method<S, A, R, M, MR>(&mut self, meta: S, method: M)
|
||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
|
@ -3274,7 +3355,7 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet
|
||||||
.push((meta.into(), Self::box_function_mut(function)));
|
.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)
|
fn add_async_meta_function<S, A, R, F, FR>(&mut self, meta: S, function: F)
|
||||||
where
|
where
|
||||||
S: Into<MetaMethod>,
|
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::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::{c_int, c_void};
|
use std::os::raw::{c_int, c_void};
|
||||||
use std::ptr;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
|
@ -18,8 +17,8 @@ use crate::userdata::{
|
||||||
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
||||||
};
|
};
|
||||||
use crate::util::{
|
use crate::util::{
|
||||||
assert_stack, check_stack, get_userdata, init_userdata_metatable, push_table, rawset_field,
|
assert_stack, check_stack, get_userdata, init_userdata_metatable, push_table, push_userdata,
|
||||||
take_userdata, StackGuard,
|
rawset_field, take_userdata, StackGuard,
|
||||||
};
|
};
|
||||||
use crate::value::{FromLua, FromLuaMulti, MultiValue, ToLua, ToLuaMulti, Value};
|
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_pushnil(state);
|
||||||
ffi::lua_setiuservalue(state, -2, i as c_int);
|
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_pushnil(state);
|
||||||
ffi::lua_setuservalue(state, -2);
|
ffi::lua_setuservalue(state, -2);
|
||||||
|
@ -264,7 +263,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||||
fn wrap_method<'scope, 'lua, 'callback: 'scope, T: 'scope>(
|
fn wrap_method<'scope, 'lua, 'callback: 'scope, T: 'scope>(
|
||||||
scope: &Scope<'lua, 'scope>,
|
scope: &Scope<'lua, 'scope>,
|
||||||
data: Rc<RefCell<T>>,
|
data: Rc<RefCell<T>>,
|
||||||
data_ptr: *const c_void,
|
ud_ptr: *const c_void,
|
||||||
method: NonStaticMethod<'callback, T>,
|
method: NonStaticMethod<'callback, T>,
|
||||||
) -> Result<Function<'lua>> {
|
) -> Result<Function<'lua>> {
|
||||||
// On methods that actually receive the userdata, we fake a type check on the passed in
|
// 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);
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 2)?;
|
check_stack(lua.state, 2)?;
|
||||||
lua.push_userdata_ref(&ud.0)?;
|
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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,8 +335,9 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||||
let _sg = StackGuard::new(lua.state);
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 13)?;
|
check_stack(lua.state, 13)?;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
#[allow(clippy::let_and_return)]
|
#[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 =
|
let ud =
|
||||||
ffi::lua_newuserdata(state, mem::size_of::<UserDataCell<Rc<RefCell<T>>>>());
|
ffi::lua_newuserdata(state, mem::size_of::<UserDataCell<Rc<RefCell<T>>>>());
|
||||||
|
|
||||||
|
@ -350,13 +350,22 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||||
|
|
||||||
ud
|
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
|
// 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;
|
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)?;
|
push_table(lua.state, 0, meta_methods_nrec as c_int)?;
|
||||||
|
|
||||||
for (k, m) in ud_methods.meta_methods {
|
for (k, m) in ud_methods.meta_methods {
|
||||||
let data = data.clone();
|
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())?;
|
rawset_field(lua.state, -2, k.validate()?.name())?;
|
||||||
}
|
}
|
||||||
for (k, f) in ud_fields.meta_fields {
|
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)?;
|
push_table(lua.state, 0, field_getters_nrec as c_int)?;
|
||||||
for (k, m) in ud_fields.field_getters {
|
for (k, m) in ud_fields.field_getters {
|
||||||
let data = data.clone();
|
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)?;
|
rawset_field(lua.state, -2, &k)?;
|
||||||
}
|
}
|
||||||
field_getters_index = Some(ffi::lua_absindex(lua.state, -1));
|
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)?;
|
push_table(lua.state, 0, field_setters_nrec as c_int)?;
|
||||||
for (k, m) in ud_fields.field_setters {
|
for (k, m) in ud_fields.field_setters {
|
||||||
let data = data.clone();
|
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)?;
|
rawset_field(lua.state, -2, &k)?;
|
||||||
}
|
}
|
||||||
field_setters_index = Some(ffi::lua_absindex(lua.state, -1));
|
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)?;
|
push_table(lua.state, 0, methods_nrec as c_int)?;
|
||||||
for (k, m) in ud_methods.methods {
|
for (k, m) in ud_methods.methods {
|
||||||
let data = data.clone();
|
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)?;
|
rawset_field(lua.state, -2, &k)?;
|
||||||
}
|
}
|
||||||
methods_index = Some(ffi::lua_absindex(lua.state, -1));
|
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);
|
let mt_ptr = ffi::lua_topointer(lua.state, -1);
|
||||||
// Write userdata just before attaching metatable with `__gc` metamethod
|
// 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);
|
ffi::lua_setmetatable(lua.state, -2);
|
||||||
let ud = AnyUserData(lua.pop_ref());
|
let ud = AnyUserData(lua.pop_ref());
|
||||||
lua.register_userdata_metatable(mt_ptr, None);
|
lua.register_userdata_metatable(mt_ptr, None);
|
||||||
|
@ -446,7 +456,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||||
ffi::lua_pushnil(state);
|
ffi::lua_pushnil(state);
|
||||||
ffi::lua_setiuservalue(state, -2, i as c_int);
|
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_pushnil(state);
|
||||||
ffi::lua_setuservalue(state, -2);
|
ffi::lua_setuservalue(state, -2);
|
||||||
|
@ -532,7 +542,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
||||||
// First, get the environment table
|
// First, get the environment table
|
||||||
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
|
||||||
ffi::lua_getupvalue(state, -1, 1);
|
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);
|
ffi::lua_getfenv(state, -1);
|
||||||
|
|
||||||
// Second, get the `get_poll()` closure using the corresponding key
|
// 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)
|
fn add_async_meta_method<S, A, R, M, MR>(&mut self, _meta: S, _method: M)
|
||||||
where
|
where
|
||||||
T: Clone,
|
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)
|
fn add_async_meta_function<S, A, R, F, FR>(&mut self, _meta: S, _function: F)
|
||||||
where
|
where
|
||||||
S: Into<MetaMethod>,
|
S: Into<MetaMethod>,
|
||||||
|
|
|
@ -9,11 +9,17 @@ impl StdLib {
|
||||||
/// [`coroutine`](https://www.lua.org/manual/5.4/manual.html#6.2) library
|
/// [`coroutine`](https://www.lua.org/manual/5.4/manual.html#6.2) library
|
||||||
///
|
///
|
||||||
/// Requires `feature = "lua54/lua53/lua52"`
|
/// 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);
|
pub const COROUTINE: StdLib = StdLib(1);
|
||||||
/// [`table`](https://www.lua.org/manual/5.4/manual.html#6.6) library
|
/// [`table`](https://www.lua.org/manual/5.4/manual.html#6.6) library
|
||||||
pub const TABLE: StdLib = StdLib(1 << 1);
|
pub const TABLE: StdLib = StdLib(1 << 1);
|
||||||
/// [`io`](https://www.lua.org/manual/5.4/manual.html#6.8) library
|
/// [`io`](https://www.lua.org/manual/5.4/manual.html#6.8) library
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub const IO: StdLib = StdLib(1 << 2);
|
pub const IO: StdLib = StdLib(1 << 2);
|
||||||
/// [`os`](https://www.lua.org/manual/5.4/manual.html#6.9) library
|
/// [`os`](https://www.lua.org/manual/5.4/manual.html#6.9) library
|
||||||
pub const OS: StdLib = StdLib(1 << 3);
|
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
|
/// [`utf8`](https://www.lua.org/manual/5.4/manual.html#6.5) library
|
||||||
///
|
///
|
||||||
/// Requires `feature = "lua54/lua53"`
|
/// 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);
|
pub const UTF8: StdLib = StdLib(1 << 5);
|
||||||
/// [`bit`](https://www.lua.org/manual/5.2/manual.html#6.7) library
|
/// [`bit`](https://www.lua.org/manual/5.2/manual.html#6.7) library
|
||||||
///
|
///
|
||||||
/// Requires `feature = "lua52/luajit"`
|
/// 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);
|
pub const BIT: StdLib = StdLib(1 << 6);
|
||||||
/// [`math`](https://www.lua.org/manual/5.4/manual.html#6.7) library
|
/// [`math`](https://www.lua.org/manual/5.4/manual.html#6.7) library
|
||||||
pub const MATH: StdLib = StdLib(1 << 7);
|
pub const MATH: StdLib = StdLib(1 << 7);
|
||||||
/// [`package`](https://www.lua.org/manual/5.4/manual.html#6.3) library
|
/// [`package`](https://www.lua.org/manual/5.4/manual.html#6.3) library
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub const PACKAGE: StdLib = StdLib(1 << 8);
|
pub const PACKAGE: StdLib = StdLib(1 << 8);
|
||||||
/// [`jit`](http://luajit.org/ext_jit.html) library
|
/// [`jit`](http://luajit.org/ext_jit.html) library
|
||||||
///
|
///
|
||||||
|
|
|
@ -11,6 +11,7 @@ use futures_core::future::LocalBoxFuture;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
use crate::hook::Debug;
|
use crate::hook::Debug;
|
||||||
use crate::lua::Lua;
|
use crate::lua::Lua;
|
||||||
use crate::util::{assert_stack, StackGuard};
|
use crate::util::{assert_stack, StackGuard};
|
||||||
|
@ -48,11 +49,10 @@ pub(crate) struct AsyncPollUpvalue<'lua> {
|
||||||
pub(crate) lua: Lua,
|
pub(crate) lua: Lua,
|
||||||
pub(crate) fut: LocalBoxFuture<'lua, Result<MultiValue<'lua>>>,
|
pub(crate) fut: LocalBoxFuture<'lua, Result<MultiValue<'lua>>>,
|
||||||
}
|
}
|
||||||
|
#[cfg(all(feature = "send", not(feature = "luau")))]
|
||||||
#[cfg(feature = "send")]
|
|
||||||
pub(crate) type HookCallback = Arc<Mutex<dyn FnMut(&Lua, Debug) -> Result<()> + Send>>;
|
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<()>>>;
|
pub(crate) type HookCallback = Arc<Mutex<dyn FnMut(&Lua, Debug) -> Result<()>>>;
|
||||||
|
|
||||||
#[cfg(all(feature = "send", feature = "lua54"))]
|
#[cfg(all(feature = "send", feature = "lua54"))]
|
||||||
|
|
|
@ -419,7 +419,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
||||||
/// Requires `feature = "async"`
|
/// Requires `feature = "async"`
|
||||||
///
|
///
|
||||||
/// [`add_meta_method`]: #method.add_meta_method
|
/// [`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")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||||
fn add_async_meta_method<S, A, R, M, MR>(&mut self, name: S, method: M)
|
fn add_async_meta_method<S, A, R, M, MR>(&mut self, name: S, method: M)
|
||||||
where
|
where
|
||||||
|
@ -461,7 +461,7 @@ pub trait UserDataMethods<'lua, T: UserData> {
|
||||||
/// Requires `feature = "async"`
|
/// Requires `feature = "async"`
|
||||||
///
|
///
|
||||||
/// [`add_meta_function`]: #method.add_meta_function
|
/// [`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")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||||
fn add_async_meta_function<S, A, R, F, FR>(&mut self, name: S, function: F)
|
fn add_async_meta_function<S, A, R, F, FR>(&mut self, name: S, function: F)
|
||||||
where
|
where
|
||||||
|
@ -839,7 +839,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
ffi::lua_pushnil(lua.state);
|
ffi::lua_pushnil(lua.state);
|
||||||
ffi::lua_setiuservalue(lua.state, -2, i as c_int);
|
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_pushnil(lua.state);
|
||||||
ffi::lua_setuservalue(lua.state, -2);
|
ffi::lua_setuservalue(lua.state, -2);
|
||||||
|
@ -865,6 +865,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
///
|
///
|
||||||
/// [`get_user_value`]: #method.get_user_value
|
/// [`get_user_value`]: #method.get_user_value
|
||||||
/// [`set_nth_user_value`]: #method.set_nth_user_value
|
/// [`set_nth_user_value`]: #method.set_nth_user_value
|
||||||
|
// #[cfg(not(feature = "luau"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
|
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
|
||||||
self.set_nth_user_value(1, v)
|
self.set_nth_user_value(1, v)
|
||||||
|
@ -876,6 +877,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
///
|
///
|
||||||
/// [`set_user_value`]: #method.set_user_value
|
/// [`set_user_value`]: #method.set_user_value
|
||||||
/// [`get_nth_user_value`]: #method.get_nth_user_value
|
/// [`get_nth_user_value`]: #method.get_nth_user_value
|
||||||
|
// #[cfg(not(feature = "luau"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
|
pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
|
||||||
self.get_nth_user_value(1)
|
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.
|
/// For other Lua versions this functionality is provided using a wrapping table.
|
||||||
///
|
///
|
||||||
/// [`get_nth_user_value`]: #method.get_nth_user_value
|
/// [`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<()> {
|
pub fn set_nth_user_value<V: ToLua<'lua>>(&self, n: usize, v: V) -> Result<()> {
|
||||||
if n < 1 || n > u16::MAX as usize {
|
if n < 1 || n > u16::MAX as usize {
|
||||||
return Err(Error::RuntimeError(
|
return Err(Error::RuntimeError(
|
||||||
|
@ -945,6 +948,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
/// For other Lua versions this functionality is provided using a wrapping table.
|
/// For other Lua versions this functionality is provided using a wrapping table.
|
||||||
///
|
///
|
||||||
/// [`set_nth_user_value`]: #method.set_nth_user_value
|
/// [`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> {
|
pub fn get_nth_user_value<V: FromLua<'lua>>(&self, n: usize) -> Result<V> {
|
||||||
if n < 1 || n > u16::MAX as usize {
|
if n < 1 || n > u16::MAX as usize {
|
||||||
return Err(Error::RuntimeError(
|
return Err(Error::RuntimeError(
|
||||||
|
@ -986,6 +990,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
/// The value can be retrieved with [`get_named_user_value`].
|
/// The value can be retrieved with [`get_named_user_value`].
|
||||||
///
|
///
|
||||||
/// [`get_named_user_value`]: #method.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<()>
|
pub fn set_named_user_value<S, V>(&self, name: &S, v: V) -> Result<()>
|
||||||
where
|
where
|
||||||
S: AsRef<[u8]> + ?Sized,
|
S: AsRef<[u8]> + ?Sized,
|
||||||
|
@ -1025,6 +1030,7 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
/// Returns an associated value by name set by [`set_named_user_value`].
|
/// Returns an associated value by name set by [`set_named_user_value`].
|
||||||
///
|
///
|
||||||
/// [`set_named_user_value`]: #method.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>
|
pub fn get_named_user_value<S, V>(&self, name: &S) -> Result<V>
|
||||||
where
|
where
|
||||||
S: AsRef<[u8]> + ?Sized,
|
S: AsRef<[u8]> + ?Sized,
|
||||||
|
|
64
src/util.rs
64
src/util.rs
|
@ -278,6 +278,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internally uses 3 stack spaces, does not call checkstack.
|
// Internally uses 3 stack spaces, does not call checkstack.
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T) -> Result<()> {
|
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T) -> Result<()> {
|
||||||
let ud = protect_lua!(state, 0, 1, |state| {
|
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(())
|
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.
|
// Internally uses 3 stack spaces, does not call checkstack.
|
||||||
#[cfg(feature = "lua54")]
|
#[cfg(feature = "lua54")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -316,8 +338,11 @@ pub unsafe fn take_userdata<T>(state: *mut ffi::lua_State) -> T {
|
||||||
// after the first call to __gc.
|
// after the first call to __gc.
|
||||||
get_destructed_userdata_metatable(state);
|
get_destructed_userdata_metatable(state);
|
||||||
ffi::lua_setmetatable(state, -2);
|
ffi::lua_setmetatable(state, -2);
|
||||||
let ud = get_userdata(state, -1);
|
let ud = get_userdata::<T>(state, -1);
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
|
if cfg!(feature = "luau") {
|
||||||
|
*(ud.offset(1) as *mut u8) = 1; // Mark as destructed
|
||||||
|
}
|
||||||
ptr::read(ud)
|
ptr::read(ud)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,8 +533,11 @@ pub unsafe fn init_userdata_metatable<T>(
|
||||||
rawset_field(state, -2, "__newindex")?;
|
rawset_field(state, -2, "__newindex")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
|
#[cfg(not(feature = "luau"))]
|
||||||
rawset_field(state, -2, "__gc")?;
|
{
|
||||||
|
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
|
||||||
|
rawset_field(state, -2, "__gc")?;
|
||||||
|
}
|
||||||
|
|
||||||
ffi::lua_pushboolean(state, 0);
|
ffi::lua_pushboolean(state, 0);
|
||||||
rawset_field(state, -2, "__metatable")?;
|
rawset_field(state, -2, "__metatable")?;
|
||||||
|
@ -519,6 +547,7 @@ pub unsafe fn init_userdata_metatable<T>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
pub unsafe extern "C" fn userdata_destructor<T>(state: *mut ffi::lua_State) -> c_int {
|
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
|
// 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
|
// 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
|
// We cannot shadow Rust errors with Lua ones, we pre-allocate enough memory
|
||||||
// to store a wrapped error or panic *before* we proceed.
|
// 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);
|
ffi::lua_rotate(state, 1, 1);
|
||||||
|
|
||||||
match catch_unwind(AssertUnwindSafe(|| f(nargs))) {
|
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
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "luau")]
|
||||||
|
Some(ffi::lua_mainthread(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the internal (with __gc method) metatable for a type T.
|
// 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)?;
|
push_table(state, 0, 3)?;
|
||||||
|
|
||||||
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
|
#[cfg(not(feature = "luau"))]
|
||||||
rawset_field(state, -2, "__gc")?;
|
{
|
||||||
|
ffi::lua_pushcfunction(state, userdata_destructor::<T>);
|
||||||
|
rawset_field(state, -2, "__gc")?;
|
||||||
|
}
|
||||||
|
|
||||||
ffi::lua_pushboolean(state, 0);
|
ffi::lua_pushboolean(state, 0);
|
||||||
rawset_field(state, -2, "__metatable")?;
|
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 {
|
pub(crate) enum WrappedFailure {
|
||||||
|
None,
|
||||||
Error(Error),
|
Error(Error),
|
||||||
Panic(Option<Box<dyn Any + Send + 'static>>),
|
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
|
// Converts the given lua value to a string in a reasonable format without causing a Lua error or
|
||||||
// panicking.
|
// panicking.
|
||||||
pub(crate) unsafe fn to_string(state: *mut ffi::lua_State, index: c_int) -> String {
|
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))
|
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 {
|
methods.add_async_meta_method(mlua::MetaMethod::Call, |_, data, ()| async move {
|
||||||
let n = data.0.load(Ordering::Relaxed);
|
let n = data.0.load(Ordering::Relaxed);
|
||||||
Delay::new(Duration::from_millis(n)).await;
|
Delay::new(Duration::from_millis(n)).await;
|
||||||
|
@ -363,7 +363,7 @@ async fn test_async_userdata() -> Result<()> {
|
||||||
.exec_async()
|
.exec_async()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
#[cfg(not(feature = "lua51"))]
|
#[cfg(not(any(feature = "lua51", feature = "luau")))]
|
||||||
lua.load(
|
lua.load(
|
||||||
r#"
|
r#"
|
||||||
userdata:set_value(15)
|
userdata:set_value(15)
|
||||||
|
|
|
@ -93,6 +93,7 @@ fn test_c_function() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dump() -> Result<()> {
|
fn test_dump() -> Result<()> {
|
||||||
let lua = unsafe { Lua::unsafe_new() };
|
let lua = unsafe { Lua::unsafe_new() };
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![cfg(not(feature = "luau"))]
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
|
@ -41,7 +41,12 @@ fn test_gc_control() -> Result<()> {
|
||||||
#[cfg(feature = "lua54")]
|
#[cfg(feature = "lua54")]
|
||||||
assert_eq!(lua.gc_gen(0, 0), mlua::GCMode::Incremental);
|
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());
|
assert!(lua.gc_is_running());
|
||||||
lua.gc_stop();
|
lua.gc_stop();
|
||||||
|
|
|
@ -11,6 +11,7 @@ use mlua::{
|
||||||
UserData, Value, Variadic,
|
UserData, Value, Variadic,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_safety() -> Result<()> {
|
fn test_safety() -> Result<()> {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
@ -120,6 +121,7 @@ fn test_exec() -> Result<()> {
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.eval()?;
|
.eval()?;
|
||||||
|
println!("checkpoint");
|
||||||
assert!(module.contains_key("func")?);
|
assert!(module.contains_key("func")?);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
module.get::<_, Function>("func")?.call::<_, String>(())?,
|
module.get::<_, Function>("func")?.call::<_, String>(())?,
|
||||||
|
@ -150,6 +152,7 @@ fn test_eval() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_mode() -> Result<()> {
|
fn test_load_mode() -> Result<()> {
|
||||||
let lua = unsafe { Lua::unsafe_new() };
|
let lua = unsafe { Lua::unsafe_new() };
|
||||||
|
@ -250,15 +253,7 @@ fn test_error() -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for TestError {
|
impl error::Error for TestError {}
|
||||||
fn description(&self) -> &str {
|
|
||||||
"test error"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cause(&self) -> Option<&dyn error::Error> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
|
||||||
|
@ -295,8 +290,8 @@ fn test_error() -> Result<()> {
|
||||||
end, 3)
|
end, 3)
|
||||||
|
|
||||||
local function handler(err)
|
local function handler(err)
|
||||||
if string.match(_VERSION, ' 5%.1$') or string.match(_VERSION, ' 5%.2$') then
|
if string.match(_VERSION, ' 5%.1$') or string.match(_VERSION, ' 5%.2$') or _VERSION == "Luau" then
|
||||||
-- Special case for Lua 5.1/5.2
|
-- Special case for Lua 5.1/5.2 and Luau
|
||||||
local caps = string.match(err, ': (%d+)$')
|
local caps = string.match(err, ': (%d+)$')
|
||||||
if caps then
|
if caps then
|
||||||
err = caps
|
err = caps
|
||||||
|
@ -1096,7 +1091,11 @@ fn test_context_thread() -> Result<()> {
|
||||||
))]
|
))]
|
||||||
f.call::<_, ()>(lua.current_thread())?;
|
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)?;
|
f.call::<_, ()>(Nil)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1170,6 +1169,7 @@ fn test_load_from_function() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "luau"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inspect_stack() -> Result<()> {
|
fn test_inspect_stack() -> Result<()> {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
|
|
@ -155,7 +155,8 @@ fn test_coroutine_from_closure() -> Result<()> {
|
||||||
feature = "lua54",
|
feature = "lua54",
|
||||||
feature = "lua53",
|
feature = "lua53",
|
||||||
feature = "lua52",
|
feature = "lua52",
|
||||||
feature = "luajit"
|
feature = "luajit",
|
||||||
|
feature = "luau"
|
||||||
))]
|
))]
|
||||||
let thrd: Thread = lua.load("coroutine.create(main)").eval()?;
|
let thrd: Thread = lua.load("coroutine.create(main)").eval()?;
|
||||||
#[cfg(feature = "lua51")]
|
#[cfg(feature = "lua51")]
|
||||||
|
|
|
@ -350,7 +350,7 @@ fn test_userdata_take() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_destroy_userdata() -> Result<()> {
|
fn test_userdata_destroy() -> Result<()> {
|
||||||
struct MyUserdata(Arc<()>);
|
struct MyUserdata(Arc<()>);
|
||||||
|
|
||||||
impl UserData for MyUserdata {}
|
impl UserData for MyUserdata {}
|
||||||
|
@ -358,12 +358,15 @@ fn test_destroy_userdata() -> Result<()> {
|
||||||
let rc = Arc::new(());
|
let rc = Arc::new(());
|
||||||
|
|
||||||
let lua = Lua::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
|
// Should destroy all objects
|
||||||
let _ = lua.globals().raw_remove("userdata")?;
|
lua.globals().raw_remove("userdata")?;
|
||||||
|
lua.gc_collect()?;
|
||||||
lua.gc_collect()?;
|
lua.gc_collect()?;
|
||||||
|
|
||||||
assert_eq!(Arc::strong_count(&rc), 1);
|
assert_eq!(Arc::strong_count(&rc), 1);
|
||||||
|
|
Loading…
Reference in New Issue