Refactor LuaInner state
Add static_assertions to check for auto traits impl on compilation stage Bump MSRV to 1.63 (required for `Ref::filter_map`)
This commit is contained in:
parent
0aa30226df
commit
9b4e3a1598
|
@ -73,6 +73,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||
serde_json = "1.0"
|
||||
maplit = "1.0"
|
||||
tempfile = "3"
|
||||
static_assertions = "1.0"
|
||||
|
||||
[[bench]]
|
||||
name = "benchmark"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[docs.rs]: https://docs.rs/mlua
|
||||
[Coverage Status]: https://codecov.io/gh/khvzak/mlua/branch/master/graph/badge.svg?token=99339FS1CG
|
||||
[codecov.io]: https://codecov.io/gh/khvzak/mlua
|
||||
[MSRV]: https://img.shields.io/badge/rust-1.56+-brightgreen.svg?&logo=rust
|
||||
[MSRV]: https://img.shields.io/badge/rust-1.63+-brightgreen.svg?&logo=rust
|
||||
|
||||
[Guided Tour] | [Benchmarks] | [FAQ]
|
||||
|
||||
|
|
|
@ -95,31 +95,32 @@ impl<'lua> Function<'lua> {
|
|||
/// ```
|
||||
pub fn call<A: ToLuaMulti<'lua>, R: FromLuaMulti<'lua>>(&self, args: A) -> Result<R> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
|
||||
let mut args = args.to_lua_multi(lua)?;
|
||||
let nargs = args.len() as c_int;
|
||||
|
||||
let results = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, nargs + 3)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, nargs + 3)?;
|
||||
|
||||
ffi::lua_pushcfunction(lua.state, error_traceback);
|
||||
let stack_start = ffi::lua_gettop(lua.state);
|
||||
ffi::lua_pushcfunction(state, error_traceback);
|
||||
let stack_start = ffi::lua_gettop(state);
|
||||
lua.push_ref(&self.0);
|
||||
for arg in args.drain_all() {
|
||||
lua.push_value(arg)?;
|
||||
}
|
||||
let ret = ffi::lua_pcall(lua.state, nargs, ffi::LUA_MULTRET, stack_start);
|
||||
let ret = ffi::lua_pcall(state, nargs, ffi::LUA_MULTRET, stack_start);
|
||||
if ret != ffi::LUA_OK {
|
||||
return Err(pop_error(lua.state, ret));
|
||||
return Err(pop_error(state, ret));
|
||||
}
|
||||
let nresults = ffi::lua_gettop(lua.state) - stack_start;
|
||||
let nresults = ffi::lua_gettop(state) - stack_start;
|
||||
let mut results = args; // Reuse MultiValue container
|
||||
assert_stack(lua.state, 2);
|
||||
assert_stack(state, 2);
|
||||
for _ in 0..nresults {
|
||||
results.push_front(lua.pop_value());
|
||||
}
|
||||
ffi::lua_pop(lua.state, 1);
|
||||
ffi::lua_pop(state, 1);
|
||||
results
|
||||
};
|
||||
R::from_lua_multi(results, lua)
|
||||
|
@ -217,6 +218,7 @@ impl<'lua> Function<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
|
||||
let args = args.to_lua_multi(lua)?;
|
||||
let nargs = args.len() as c_int;
|
||||
|
@ -230,14 +232,14 @@ impl<'lua> Function<'lua> {
|
|||
}
|
||||
|
||||
let args_wrapper = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, nargs + 3)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, nargs + 3)?;
|
||||
|
||||
ffi::lua_pushinteger(lua.state, nargs as ffi::lua_Integer);
|
||||
ffi::lua_pushinteger(state, nargs as ffi::lua_Integer);
|
||||
for arg in args {
|
||||
lua.push_value(arg)?;
|
||||
}
|
||||
protect_lua!(lua.state, nargs + 1, 1, fn(state) {
|
||||
protect_lua!(state, nargs + 1, 1, fn(state) {
|
||||
ffi::lua_pushcclosure(state, args_wrapper_impl, ffi::lua_gettop(state));
|
||||
})?;
|
||||
|
||||
|
@ -264,16 +266,17 @@ impl<'lua> Function<'lua> {
|
|||
/// [`lua_getinfo`]: https://www.lua.org/manual/5.4/manual.html#lua_getinfo
|
||||
pub fn info(&self) -> FunctionInfo {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 1);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 1);
|
||||
|
||||
let mut ar: ffi::lua_Debug = mem::zeroed();
|
||||
lua.push_ref(&self.0);
|
||||
#[cfg(not(feature = "luau"))]
|
||||
let res = ffi::lua_getinfo(lua.state, cstr!(">Sn"), &mut ar);
|
||||
let res = ffi::lua_getinfo(state, cstr!(">Sn"), &mut ar);
|
||||
#[cfg(feature = "luau")]
|
||||
let res = ffi::lua_getinfo(lua.state, -1, cstr!("sn"), &mut ar);
|
||||
let res = ffi::lua_getinfo(state, -1, cstr!("sn"), &mut ar);
|
||||
mlua_assert!(res != 0, "lua_getinfo failed with `>Sn`");
|
||||
|
||||
FunctionInfo {
|
||||
|
@ -319,15 +322,16 @@ impl<'lua> Function<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 1);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 1);
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
let data_ptr = &mut data as *mut Vec<u8> as *mut c_void;
|
||||
ffi::lua_dump(lua.state, writer, data_ptr, strip as i32);
|
||||
ffi::lua_pop(lua.state, 1);
|
||||
ffi::lua_dump(state, writer, data_ptr, strip as i32);
|
||||
ffi::lua_pop(state, 1);
|
||||
}
|
||||
|
||||
data
|
||||
|
@ -375,13 +379,14 @@ impl<'lua> Function<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 1);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 1);
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
let func_ptr = &mut func as *mut F as *mut c_void;
|
||||
ffi::lua_getcoverage(lua.state, -1, func_ptr, callback::<F>);
|
||||
ffi::lua_getcoverage(state, -1, func_ptr, callback::<F>);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,3 +402,10 @@ impl<'lua> PartialEq for Function<'lua> {
|
|||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_not_impl_any!(Function: Send);
|
||||
}
|
||||
|
|
18
src/hook.rs
18
src/hook.rs
|
@ -67,12 +67,12 @@ impl<'lua> Debug<'lua> {
|
|||
unsafe {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, cstr!("n"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), cstr!("n"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `n`"
|
||||
);
|
||||
#[cfg(feature = "luau")]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, self.level, cstr!("n"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), self.level, cstr!("n"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `n`"
|
||||
);
|
||||
|
||||
|
@ -91,12 +91,12 @@ impl<'lua> Debug<'lua> {
|
|||
unsafe {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, cstr!("S"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), cstr!("S"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `S`"
|
||||
);
|
||||
#[cfg(feature = "luau")]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, self.level, cstr!("s"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), self.level, cstr!("s"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `s`"
|
||||
);
|
||||
|
||||
|
@ -119,12 +119,12 @@ impl<'lua> Debug<'lua> {
|
|||
unsafe {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, cstr!("l"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), cstr!("l"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `l`"
|
||||
);
|
||||
#[cfg(feature = "luau")]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, self.level, cstr!("l"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), self.level, cstr!("l"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `l`"
|
||||
);
|
||||
|
||||
|
@ -139,7 +139,7 @@ impl<'lua> Debug<'lua> {
|
|||
pub fn is_tail_call(&self) -> bool {
|
||||
unsafe {
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, cstr!("t"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), cstr!("t"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `t`"
|
||||
);
|
||||
(*self.ar.get()).currentline != 0
|
||||
|
@ -151,12 +151,12 @@ impl<'lua> Debug<'lua> {
|
|||
unsafe {
|
||||
#[cfg(not(feature = "luau"))]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, cstr!("u"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), cstr!("u"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `u`"
|
||||
);
|
||||
#[cfg(feature = "luau")]
|
||||
mlua_assert!(
|
||||
ffi::lua_getinfo(self.lua.state, self.level, cstr!("a"), self.ar.get()) != 0,
|
||||
ffi::lua_getinfo(self.lua.state(), self.level, cstr!("a"), self.ar.get()) != 0,
|
||||
"lua_getinfo failed with `a`"
|
||||
);
|
||||
|
||||
|
|
653
src/lua.rs
653
src/lua.rs
File diff suppressed because it is too large
Load Diff
10
src/luau.rs
10
src/luau.rs
|
@ -1,5 +1,6 @@
|
|||
use std::ffi::CStr;
|
||||
use std::os::raw::{c_float, c_int};
|
||||
use std::string::String as StdString;
|
||||
|
||||
use crate::chunk::ChunkMode;
|
||||
use crate::error::{Error, Result};
|
||||
|
@ -69,14 +70,15 @@ unsafe extern "C" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_int {
|
|||
}
|
||||
}
|
||||
|
||||
fn lua_require(lua: &Lua, name: Option<std::string::String>) -> Result<Value> {
|
||||
fn lua_require(lua: &Lua, name: Option<StdString>) -> Result<Value> {
|
||||
let name = name.ok_or_else(|| Error::RuntimeError("invalid module name".into()))?;
|
||||
|
||||
// Find module in the cache
|
||||
let state = lua.state();
|
||||
let loaded = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
protect_lua!(lua.state, 0, 1, fn(state) {
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
protect_lua!(state, 0, 1, fn(state) {
|
||||
ffi::luaL_getsubtable(state, ffi::LUA_REGISTRYINDEX, cstr!("_LOADED"));
|
||||
})?;
|
||||
Table(lua.pop_ref())
|
||||
|
|
62
src/scope.rs
62
src/scope.rs
|
@ -190,7 +190,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
let newtable = self.lua.create_table()?;
|
||||
let destructor: DestructorCallback = Box::new(move |ud| {
|
||||
let state = ud.lua.state;
|
||||
let state = ud.lua.state();
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 2);
|
||||
|
||||
|
@ -275,11 +275,12 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
// first argument).
|
||||
let check_ud_type = move |lua: &'callback Lua, value| {
|
||||
if let Some(Value::UserData(ud)) = value {
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
lua.push_userdata_ref(&ud.0)?;
|
||||
if get_userdata(lua.state, -1) as *const _ == ud_ptr {
|
||||
if get_userdata(state, -1) as *const _ == ud_ptr {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
@ -330,14 +331,15 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
T::add_fields(&mut ud_fields);
|
||||
T::add_methods(&mut ud_methods);
|
||||
|
||||
let lua = self.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let lua = self.lua;
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 13)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 13)?;
|
||||
|
||||
#[cfg(not(feature = "luau"))]
|
||||
#[allow(clippy::let_and_return)]
|
||||
let ud_ptr = protect_lua!(lua.state, 0, 1, |state| {
|
||||
let ud_ptr = protect_lua!(state, 0, 1, |state| {
|
||||
let ud =
|
||||
ffi::lua_newuserdata(state, mem::size_of::<UserDataCell<Rc<RefCell<T>>>>());
|
||||
|
||||
|
@ -353,67 +355,67 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
#[cfg(feature = "luau")]
|
||||
let ud_ptr = {
|
||||
crate::util::push_userdata::<UserDataCell<Rc<RefCell<T>>>>(
|
||||
lua.state,
|
||||
state,
|
||||
UserDataCell::new(data.clone()),
|
||||
true,
|
||||
)?;
|
||||
ffi::lua_touserdata(lua.state, -1)
|
||||
ffi::lua_touserdata(state, -1)
|
||||
};
|
||||
|
||||
// Prepare metatable, add meta methods first and then meta fields
|
||||
let meta_methods_nrec = ud_methods.meta_methods.len() + ud_fields.meta_fields.len() + 1;
|
||||
push_table(lua.state, 0, meta_methods_nrec as c_int, true)?;
|
||||
push_table(state, 0, meta_methods_nrec as c_int, true)?;
|
||||
|
||||
for (k, m) in ud_methods.meta_methods {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, k.validate()?.name())?;
|
||||
rawset_field(state, -2, k.validate()?.name())?;
|
||||
}
|
||||
for (k, f) in ud_fields.meta_fields {
|
||||
lua.push_value(f(mem::transmute(lua))?)?;
|
||||
rawset_field(lua.state, -2, k.validate()?.name())?;
|
||||
rawset_field(state, -2, k.validate()?.name())?;
|
||||
}
|
||||
let metatable_index = ffi::lua_absindex(lua.state, -1);
|
||||
let metatable_index = ffi::lua_absindex(state, -1);
|
||||
|
||||
let mut field_getters_index = None;
|
||||
let field_getters_nrec = ud_fields.field_getters.len();
|
||||
if field_getters_nrec > 0 {
|
||||
push_table(lua.state, 0, field_getters_nrec as c_int, true)?;
|
||||
push_table(state, 0, field_getters_nrec as c_int, true)?;
|
||||
for (k, m) in ud_fields.field_getters {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, &k)?;
|
||||
rawset_field(state, -2, &k)?;
|
||||
}
|
||||
field_getters_index = Some(ffi::lua_absindex(lua.state, -1));
|
||||
field_getters_index = Some(ffi::lua_absindex(state, -1));
|
||||
}
|
||||
|
||||
let mut field_setters_index = None;
|
||||
let field_setters_nrec = ud_fields.field_setters.len();
|
||||
if field_setters_nrec > 0 {
|
||||
push_table(lua.state, 0, field_setters_nrec as c_int, true)?;
|
||||
push_table(state, 0, field_setters_nrec as c_int, true)?;
|
||||
for (k, m) in ud_fields.field_setters {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, &k)?;
|
||||
rawset_field(state, -2, &k)?;
|
||||
}
|
||||
field_setters_index = Some(ffi::lua_absindex(lua.state, -1));
|
||||
field_setters_index = Some(ffi::lua_absindex(state, -1));
|
||||
}
|
||||
|
||||
let mut methods_index = None;
|
||||
let methods_nrec = ud_methods.methods.len();
|
||||
if methods_nrec > 0 {
|
||||
// Create table used for methods lookup
|
||||
push_table(lua.state, 0, methods_nrec as c_int, true)?;
|
||||
push_table(state, 0, methods_nrec as c_int, true)?;
|
||||
for (k, m) in ud_methods.methods {
|
||||
let data = data.clone();
|
||||
lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?;
|
||||
rawset_field(lua.state, -2, &k)?;
|
||||
rawset_field(state, -2, &k)?;
|
||||
}
|
||||
methods_index = Some(ffi::lua_absindex(lua.state, -1));
|
||||
methods_index = Some(ffi::lua_absindex(state, -1));
|
||||
}
|
||||
|
||||
init_userdata_metatable::<UserDataCell<Rc<RefCell<T>>>>(
|
||||
lua.state,
|
||||
state,
|
||||
metatable_index,
|
||||
field_getters_index,
|
||||
field_setters_index,
|
||||
|
@ -423,20 +425,20 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
let count = field_getters_index.map(|_| 1).unwrap_or(0)
|
||||
+ field_setters_index.map(|_| 1).unwrap_or(0)
|
||||
+ methods_index.map(|_| 1).unwrap_or(0);
|
||||
ffi::lua_pop(lua.state, count);
|
||||
ffi::lua_pop(state, count);
|
||||
|
||||
let mt_ptr = ffi::lua_topointer(lua.state, -1);
|
||||
let mt_ptr = ffi::lua_topointer(state, -1);
|
||||
// Write userdata just before attaching metatable with `__gc` metamethod
|
||||
#[cfg(not(feature = "luau"))]
|
||||
std::ptr::write(ud_ptr as _, UserDataCell::new(data));
|
||||
ffi::lua_setmetatable(lua.state, -2);
|
||||
ffi::lua_setmetatable(state, -2);
|
||||
let ud = AnyUserData(lua.pop_ref());
|
||||
lua.register_userdata_metatable(mt_ptr, None);
|
||||
|
||||
#[cfg(any(feature = "lua51", feature = "luajit"))]
|
||||
let newtable = lua.create_table()?;
|
||||
let destructor: DestructorCallback = Box::new(move |ud| {
|
||||
let state = ud.lua.state;
|
||||
let state = ud.lua.state();
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 2);
|
||||
|
||||
|
@ -498,7 +500,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
let f = self.lua.create_callback(f)?;
|
||||
|
||||
let destructor: DestructorCallback = Box::new(|f| {
|
||||
let state = f.lua.state;
|
||||
let state = f.lua.state();
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 3);
|
||||
|
||||
|
@ -532,7 +534,7 @@ impl<'lua, 'scope> Scope<'lua, 'scope> {
|
|||
let get_poll_str = self.lua.create_string("get_poll")?;
|
||||
let poll_str = self.lua.create_string("poll")?;
|
||||
let destructor: DestructorCallback = Box::new(move |f| {
|
||||
let state = f.lua.state;
|
||||
let state = f.lua.state();
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 5);
|
||||
|
||||
|
|
|
@ -320,20 +320,21 @@ impl<'lua> ser::SerializeSeq for SerializeVec<'lua> {
|
|||
T: Serialize + ?Sized,
|
||||
{
|
||||
let lua = self.table.0.lua;
|
||||
let state = lua.state();
|
||||
let value = lua.to_value_with(value, self.options)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.table.0);
|
||||
lua.push_value(value)?;
|
||||
if lua.unlikely_memory_error() {
|
||||
let len = ffi::lua_rawlen(lua.state, -2) as Integer;
|
||||
ffi::lua_rawseti(lua.state, -2, len + 1);
|
||||
ffi::lua_pop(lua.state, 1);
|
||||
let len = ffi::lua_rawlen(state, -2) as Integer;
|
||||
ffi::lua_rawseti(state, -2, len + 1);
|
||||
ffi::lua_pop(state, 1);
|
||||
Ok(())
|
||||
} else {
|
||||
protect_lua!(lua.state, 2, 0, fn(state) {
|
||||
protect_lua!(state, 2, 0, fn(state) {
|
||||
let len = ffi::lua_rawlen(state, -2) as Integer;
|
||||
ffi::lua_rawseti(state, -2, len + 1);
|
||||
})
|
||||
|
|
|
@ -190,3 +190,10 @@ impl<'lua> Serialize for String<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_not_impl_any!(String: Send);
|
||||
}
|
||||
|
|
140
src/table.rs
140
src/table.rs
|
@ -78,14 +78,15 @@ impl<'lua> Table<'lua> {
|
|||
let key = key.to_lua(lua)?;
|
||||
let value = value.to_lua(lua)?;
|
||||
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 5)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(key)?;
|
||||
lua.push_value(value)?;
|
||||
protect_lua!(lua.state, 3, 0, fn(state) ffi::lua_settable(state, -3))
|
||||
protect_lua!(state, 3, 0, fn(state) ffi::lua_settable(state, -3))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,15 +121,16 @@ impl<'lua> Table<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let key = key.to_lua(lua)?;
|
||||
|
||||
let value = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(key)?;
|
||||
protect_lua!(lua.state, 2, 1, fn(state) ffi::lua_gettable(state, -2))?;
|
||||
protect_lua!(state, 2, 1, fn(state) ffi::lua_gettable(state, -2))?;
|
||||
|
||||
lua.pop_value()
|
||||
};
|
||||
|
@ -148,14 +150,15 @@ impl<'lua> Table<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let value = value.to_lua(lua)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(value)?;
|
||||
protect_lua!(lua.state, 2, 0, fn(state) {
|
||||
protect_lua!(state, 2, 0, fn(state) {
|
||||
let len = ffi::luaL_len(state, -2) as Integer;
|
||||
ffi::lua_seti(state, -2, len + 1);
|
||||
})?
|
||||
|
@ -171,12 +174,13 @@ impl<'lua> Table<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let value = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
protect_lua!(lua.state, 1, 1, fn(state) {
|
||||
protect_lua!(state, 1, 1, fn(state) {
|
||||
let len = ffi::luaL_len(state, -1) as Integer;
|
||||
ffi::lua_geti(state, -1, len);
|
||||
ffi::lua_pushnil(state);
|
||||
|
@ -249,23 +253,24 @@ impl<'lua> Table<'lua> {
|
|||
self.check_readonly_write()?;
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let key = key.to_lua(lua)?;
|
||||
let value = value.to_lua(lua)?;
|
||||
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 5)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(key)?;
|
||||
lua.push_value(value)?;
|
||||
|
||||
if lua.unlikely_memory_error() {
|
||||
ffi::lua_rawset(lua.state, -3);
|
||||
ffi::lua_pop(lua.state, 1);
|
||||
ffi::lua_rawset(state, -3);
|
||||
ffi::lua_pop(state, 1);
|
||||
Ok(())
|
||||
} else {
|
||||
protect_lua!(lua.state, 3, 0, fn(state) ffi::lua_rawset(state, -3))
|
||||
protect_lua!(state, 3, 0, fn(state) ffi::lua_rawset(state, -3))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,15 +278,16 @@ impl<'lua> Table<'lua> {
|
|||
/// Gets the value associated to `key` without invoking metamethods.
|
||||
pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let key = key.to_lua(lua)?;
|
||||
|
||||
let value = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 3)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 3)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(key)?;
|
||||
ffi::lua_rawget(lua.state, -2);
|
||||
ffi::lua_rawget(state, -2);
|
||||
|
||||
lua.pop_value()
|
||||
};
|
||||
|
@ -292,6 +298,8 @@ impl<'lua> Table<'lua> {
|
|||
/// The worst case complexity is O(n), where n is the table length.
|
||||
pub fn raw_insert<V: ToLua<'lua>>(&self, idx: Integer, value: V) -> Result<()> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
|
||||
let size = self.raw_len();
|
||||
if idx < 1 || idx > size + 1 {
|
||||
return Err(Error::RuntimeError("index out of bounds".to_string()));
|
||||
|
@ -299,12 +307,12 @@ impl<'lua> Table<'lua> {
|
|||
|
||||
let value = value.to_lua(lua)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 5)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(value)?;
|
||||
protect_lua!(lua.state, 2, 0, |state| {
|
||||
protect_lua!(state, 2, 0, |state| {
|
||||
for i in (idx..=size).rev() {
|
||||
// table[i+1] = table[i]
|
||||
ffi::lua_rawgeti(state, -2, i);
|
||||
|
@ -321,11 +329,12 @@ impl<'lua> Table<'lua> {
|
|||
self.check_readonly_write()?;
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let value = value.to_lua(lua)?;
|
||||
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
lua.push_value(value)?;
|
||||
|
@ -336,9 +345,9 @@ impl<'lua> Table<'lua> {
|
|||
}
|
||||
|
||||
if lua.unlikely_memory_error() {
|
||||
callback(lua.state);
|
||||
callback(state);
|
||||
} else {
|
||||
protect_lua!(lua.state, 2, 0, fn(state) callback(state))?;
|
||||
protect_lua!(state, 2, 0, fn(state) callback(state))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -350,16 +359,17 @@ impl<'lua> Table<'lua> {
|
|||
self.check_readonly_write()?;
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let value = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 3)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 3)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
let len = ffi::lua_rawlen(lua.state, -1) as Integer;
|
||||
ffi::lua_rawgeti(lua.state, -1, len);
|
||||
let len = ffi::lua_rawlen(state, -1) as Integer;
|
||||
ffi::lua_rawgeti(state, -1, len);
|
||||
// Set slot to nil (it must be safe to do)
|
||||
ffi::lua_pushnil(lua.state);
|
||||
ffi::lua_rawseti(lua.state, -3, len);
|
||||
ffi::lua_pushnil(state);
|
||||
ffi::lua_rawseti(state, -3, len);
|
||||
lua.pop_value()
|
||||
};
|
||||
V::from_lua(value, lua)
|
||||
|
@ -374,6 +384,7 @@ impl<'lua> Table<'lua> {
|
|||
/// For other key types this is equivalent to setting `table[key] = nil`.
|
||||
pub fn raw_remove<K: ToLua<'lua>>(&self, key: K) -> Result<()> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let key = key.to_lua(lua)?;
|
||||
match key {
|
||||
Value::Integer(idx) => {
|
||||
|
@ -382,11 +393,11 @@ impl<'lua> Table<'lua> {
|
|||
return Err(Error::RuntimeError("index out of bounds".to_string()));
|
||||
}
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
protect_lua!(lua.state, 1, 0, |state| {
|
||||
protect_lua!(state, 1, 0, |state| {
|
||||
for i in idx..size {
|
||||
ffi::lua_rawgeti(state, -1, i + 1);
|
||||
ffi::lua_rawseti(state, -2, i);
|
||||
|
@ -412,12 +423,13 @@ impl<'lua> Table<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
protect_lua!(lua.state, 1, 0, |state| ffi::luaL_len(state, -1))
|
||||
protect_lua!(state, 1, 0, |state| ffi::luaL_len(state, -1))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,12 +444,13 @@ impl<'lua> Table<'lua> {
|
|||
/// Unlike the `getmetatable` Lua function, this method ignores the `__metatable` field.
|
||||
pub fn get_metatable(&self) -> Option<Table<'lua>> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 2);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 2);
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
if ffi::lua_getmetatable(lua.state, -1) == 0 {
|
||||
if ffi::lua_getmetatable(state, -1) == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Table(lua.pop_ref()))
|
||||
|
@ -457,17 +470,18 @@ impl<'lua> Table<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 2);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 2);
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
if let Some(metatable) = metatable {
|
||||
lua.push_ref(&metatable.0);
|
||||
} else {
|
||||
ffi::lua_pushnil(lua.state);
|
||||
ffi::lua_pushnil(state);
|
||||
}
|
||||
ffi::lua_setmetatable(lua.state, -2);
|
||||
ffi::lua_setmetatable(state, -2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -654,16 +668,17 @@ impl<'lua> Table<'lua> {
|
|||
#[cfg(feature = "serialize")]
|
||||
pub(crate) fn is_array(&self) -> bool {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 3);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 3);
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
if ffi::lua_getmetatable(lua.state, -1) == 0 {
|
||||
if ffi::lua_getmetatable(state, -1) == 0 {
|
||||
return false;
|
||||
}
|
||||
crate::serde::push_array_metatable(lua.state);
|
||||
ffi::lua_rawequal(lua.state, -1, -2) != 0
|
||||
crate::serde::push_array_metatable(state);
|
||||
ffi::lua_rawequal(state, -1, -2) != 0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -911,15 +926,16 @@ where
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(prev_key) = self.key.take() {
|
||||
let lua = self.table.lua;
|
||||
let state = lua.state();
|
||||
|
||||
let res = (|| unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 5)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_ref(&self.table);
|
||||
lua.push_value(prev_key)?;
|
||||
|
||||
let next = protect_lua!(lua.state, 2, ffi::LUA_MULTRET, |state| {
|
||||
let next = protect_lua!(state, 2, ffi::LUA_MULTRET, |state| {
|
||||
ffi::lua_next(state, -2)
|
||||
})?;
|
||||
if next != 0 {
|
||||
|
@ -971,16 +987,17 @@ where
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(index) = self.index.take() {
|
||||
let lua = self.table.lua;
|
||||
let state = lua.state();
|
||||
|
||||
let res = (|| unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 1 + if self.raw { 0 } else { 3 })?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 1 + if self.raw { 0 } else { 3 })?;
|
||||
|
||||
lua.push_ref(&self.table);
|
||||
let res = if self.raw {
|
||||
ffi::lua_rawgeti(lua.state, -1, index)
|
||||
ffi::lua_rawgeti(state, -1, index)
|
||||
} else {
|
||||
protect_lua!(lua.state, 1, 1, |state| ffi::lua_geti(state, -1, index))?
|
||||
protect_lua!(state, 1, 1, |state| ffi::lua_geti(state, -1, index))?
|
||||
};
|
||||
match res {
|
||||
ffi::LUA_TNIL if index > self.len.unwrap_or(0) => Ok(None),
|
||||
|
@ -1001,3 +1018,10 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_not_impl_any!(Table: Send);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ use {
|
|||
},
|
||||
futures_core::{future::Future, stream::Stream},
|
||||
std::{
|
||||
cell::RefCell,
|
||||
marker::PhantomData,
|
||||
pin::Pin,
|
||||
task::{Context, Poll, Waker},
|
||||
|
@ -67,10 +66,9 @@ impl OwnedThread {
|
|||
/// [`Stream`]: futures_core::stream::Stream
|
||||
#[cfg(feature = "async")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
|
||||
#[derive(Debug)]
|
||||
pub struct AsyncThread<'lua, R> {
|
||||
thread: Thread<'lua>,
|
||||
args0: RefCell<Option<Result<MultiValue<'lua>>>>,
|
||||
args0: Option<Result<MultiValue<'lua>>>,
|
||||
ret: PhantomData<R>,
|
||||
recycle: bool,
|
||||
}
|
||||
|
@ -123,11 +121,13 @@ impl<'lua> Thread<'lua> {
|
|||
R: FromLuaMulti<'lua>,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
|
||||
let mut args = args.to_lua_multi(lua)?;
|
||||
let nargs = args.len() as c_int;
|
||||
let results = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, cmp::max(nargs + 1, 3))?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, cmp::max(nargs + 1, 3))?;
|
||||
|
||||
let thread_state = ffi::lua_tothread(lua.ref_thread(), self.0.index);
|
||||
|
||||
|
@ -140,23 +140,23 @@ impl<'lua> Thread<'lua> {
|
|||
for arg in args.drain_all() {
|
||||
lua.push_value(arg)?;
|
||||
}
|
||||
ffi::lua_xmove(lua.state, thread_state, nargs);
|
||||
ffi::lua_xmove(state, thread_state, nargs);
|
||||
|
||||
let mut nresults = 0;
|
||||
|
||||
let ret = ffi::lua_resume(thread_state, lua.state, nargs, &mut nresults as *mut c_int);
|
||||
let ret = ffi::lua_resume(thread_state, state, nargs, &mut nresults as *mut c_int);
|
||||
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
|
||||
check_stack(lua.state, 3)?;
|
||||
protect_lua!(lua.state, 0, 1, |state| error_traceback_thread(
|
||||
check_stack(state, 3)?;
|
||||
protect_lua!(state, 0, 1, |state| error_traceback_thread(
|
||||
state,
|
||||
thread_state
|
||||
))?;
|
||||
return Err(pop_error(lua.state, ret));
|
||||
return Err(pop_error(state, ret));
|
||||
}
|
||||
|
||||
let mut results = args; // Reuse MultiValue container
|
||||
check_stack(lua.state, nresults + 2)?; // 2 is extra for `lua.pop_value()` below
|
||||
ffi::lua_xmove(thread_state, lua.state, nresults);
|
||||
check_stack(state, nresults + 2)?; // 2 is extra for `lua.pop_value()` below
|
||||
ffi::lua_xmove(thread_state, state, nresults);
|
||||
|
||||
for _ in 0..nresults {
|
||||
results.push_front(lua.pop_value());
|
||||
|
@ -205,12 +205,13 @@ impl<'lua> Thread<'lua> {
|
|||
))]
|
||||
pub fn reset(&self, func: Function<'lua>) -> Result<()> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
lua.push_ref(&self.0);
|
||||
let thread_state = ffi::lua_tothread(lua.state, -1);
|
||||
let thread_state = ffi::lua_tothread(state, -1);
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
let status = ffi::lua_resetthread(thread_state);
|
||||
|
@ -219,17 +220,17 @@ impl<'lua> Thread<'lua> {
|
|||
return Err(pop_error(thread_state, status));
|
||||
}
|
||||
#[cfg(all(feature = "luajit", feature = "vendored"))]
|
||||
ffi::lua_resetthread(lua.state, thread_state);
|
||||
ffi::lua_resetthread(state, thread_state);
|
||||
#[cfg(feature = "luau")]
|
||||
ffi::lua_resetthread(thread_state);
|
||||
|
||||
lua.push_ref(&func.0);
|
||||
ffi::lua_xmove(lua.state, thread_state, 1);
|
||||
ffi::lua_xmove(state, thread_state, 1);
|
||||
|
||||
#[cfg(feature = "luau")]
|
||||
{
|
||||
// Inherit `LUA_GLOBALSINDEX` from the caller
|
||||
ffi::lua_xpush(lua.state, thread_state, ffi::LUA_GLOBALSINDEX);
|
||||
ffi::lua_xpush(state, thread_state, ffi::LUA_GLOBALSINDEX);
|
||||
ffi::lua_replace(thread_state, ffi::LUA_GLOBALSINDEX);
|
||||
}
|
||||
|
||||
|
@ -292,7 +293,7 @@ impl<'lua> Thread<'lua> {
|
|||
let args = args.to_lua_multi(self.0.lua);
|
||||
AsyncThread {
|
||||
thread: self,
|
||||
args0: RefCell::new(Some(args)),
|
||||
args0: Some(args),
|
||||
ret: PhantomData,
|
||||
recycle: false,
|
||||
}
|
||||
|
@ -334,14 +335,15 @@ impl<'lua> Thread<'lua> {
|
|||
#[doc(hidden)]
|
||||
pub fn sandbox(&self) -> Result<()> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let thread = ffi::lua_tothread(lua.ref_thread(), self.0.index);
|
||||
check_stack(thread, 1)?;
|
||||
check_stack(lua.state, 3)?;
|
||||
check_stack(state, 3)?;
|
||||
// Inherit `LUA_GLOBALSINDEX` from the caller
|
||||
ffi::lua_xpush(lua.state, thread, ffi::LUA_GLOBALSINDEX);
|
||||
ffi::lua_xpush(state, thread, ffi::LUA_GLOBALSINDEX);
|
||||
ffi::lua_replace(thread, ffi::LUA_GLOBALSINDEX);
|
||||
protect_lua!(lua.state, 0, 0, |_| ffi::luaL_sandboxthread(thread))
|
||||
protect_lua!(state, 0, 0, |_| ffi::luaL_sandboxthread(thread))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,10 +408,13 @@ where
|
|||
};
|
||||
|
||||
let _wg = WakerGuard::new(lua, cx.waker().clone());
|
||||
let ret: MultiValue = if let Some(args) = self.args0.borrow_mut().take() {
|
||||
self.thread.resume(args?)?
|
||||
|
||||
// This is safe as we are not moving the whole struct
|
||||
let this = unsafe { self.get_unchecked_mut() };
|
||||
let ret: MultiValue = if let Some(args) = this.args0.take() {
|
||||
this.thread.resume(args?)?
|
||||
} else {
|
||||
self.thread.resume(())?
|
||||
this.thread.resume(())?
|
||||
};
|
||||
|
||||
if is_poll_pending(&ret) {
|
||||
|
@ -437,17 +442,20 @@ where
|
|||
};
|
||||
|
||||
let _wg = WakerGuard::new(lua, cx.waker().clone());
|
||||
let ret: MultiValue = if let Some(args) = self.args0.borrow_mut().take() {
|
||||
self.thread.resume(args?)?
|
||||
|
||||
// This is safe as we are not moving the whole struct
|
||||
let this = unsafe { self.get_unchecked_mut() };
|
||||
let ret: MultiValue = if let Some(args) = this.args0.take() {
|
||||
this.thread.resume(args?)?
|
||||
} else {
|
||||
self.thread.resume(())?
|
||||
this.thread.resume(())?
|
||||
};
|
||||
|
||||
if is_poll_pending(&ret) {
|
||||
return Poll::Pending;
|
||||
}
|
||||
|
||||
if let ThreadStatus::Resumable = self.thread.status() {
|
||||
if let ThreadStatus::Resumable = this.thread.status() {
|
||||
// Ignore value returned via yield()
|
||||
cx.waker().wake_by_ref();
|
||||
return Poll::Pending;
|
||||
|
@ -493,3 +501,10 @@ impl<'lua> Drop for WakerGuard<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_not_impl_any!(Thread: Send);
|
||||
}
|
||||
|
|
20
src/types.rs
20
src/types.rs
|
@ -192,6 +192,7 @@ impl<'lua> LuaRef<'lua> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn into_owned(self) -> LuaOwnedRef {
|
||||
self.lua.make_owned_ref(self)
|
||||
}
|
||||
|
@ -220,12 +221,13 @@ impl<'lua> Drop for LuaRef<'lua> {
|
|||
impl<'lua> PartialEq for LuaRef<'lua> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let lua = self.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
assert_stack(lua.state, 2);
|
||||
let _sg = StackGuard::new(state);
|
||||
assert_stack(state, 2);
|
||||
lua.push_ref(self);
|
||||
lua.push_ref(other);
|
||||
ffi::lua_rawequal(lua.state, -1, -2) == 1
|
||||
ffi::lua_rawequal(state, -1, -2) == 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,10 +251,10 @@ impl Clone for LuaOwnedRef {
|
|||
|
||||
impl Drop for LuaOwnedRef {
|
||||
fn drop(&mut self) {
|
||||
self.lua.drop_ref(&LuaRef {
|
||||
drop(LuaRef {
|
||||
lua: &self.lua,
|
||||
index: self.index,
|
||||
drop: false,
|
||||
drop: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -266,3 +268,11 @@ impl LuaOwnedRef {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_impl_all!(RegistryKey: Send, Sync);
|
||||
static_assertions::assert_not_impl_any!(LuaRef: Send);
|
||||
}
|
||||
|
|
|
@ -829,16 +829,17 @@ impl<'lua> AnyUserData<'lua> {
|
|||
/// Keeps associated user values unchanged (they will be collected by Lua's GC).
|
||||
pub fn take<T: 'static + UserData>(&self) -> Result<T> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = lua.push_userdata_ref(&self.0)?;
|
||||
match type_id {
|
||||
Some(type_id) if type_id == TypeId::of::<T>() => {
|
||||
// Try to borrow userdata exclusively
|
||||
let _ = (*get_userdata::<UserDataCell<T>>(lua.state, -1)).try_borrow_mut()?;
|
||||
Ok(take_userdata::<UserDataCell<T>>(lua.state).into_inner())
|
||||
let _ = (*get_userdata::<UserDataCell<T>>(state, -1)).try_borrow_mut()?;
|
||||
Ok(take_userdata::<UserDataCell<T>>(state).into_inner())
|
||||
}
|
||||
_ => Err(Error::UserDataTypeMismatch),
|
||||
}
|
||||
|
@ -887,21 +888,22 @@ impl<'lua> AnyUserData<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 5)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0)?;
|
||||
lua.push_value(v.to_lua(lua)?)?;
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
if n < USER_VALUE_MAXSLOT {
|
||||
ffi::lua_setiuservalue(lua.state, -2, n as c_int);
|
||||
ffi::lua_setiuservalue(state, -2, n as c_int);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Multiple (extra) user values are emulated by storing them in a table
|
||||
protect_lua!(lua.state, 2, 0, |state| {
|
||||
protect_lua!(state, 2, 0, |state| {
|
||||
if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
|
||||
// Create a new table to use as uservalue
|
||||
ffi::lua_pop(state, 1);
|
||||
|
@ -941,20 +943,21 @@ impl<'lua> AnyUserData<'lua> {
|
|||
}
|
||||
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0)?;
|
||||
|
||||
#[cfg(feature = "lua54")]
|
||||
if n < USER_VALUE_MAXSLOT {
|
||||
ffi::lua_getiuservalue(lua.state, -1, n as c_int);
|
||||
ffi::lua_getiuservalue(state, -1, n as c_int);
|
||||
return V::from_lua(lua.pop_value(), lua);
|
||||
}
|
||||
|
||||
// Multiple (extra) user values are emulated by storing them in a table
|
||||
protect_lua!(lua.state, 1, 1, |state| {
|
||||
protect_lua!(state, 1, 1, |state| {
|
||||
if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
|
||||
ffi::lua_pushnil(state);
|
||||
return;
|
||||
|
@ -979,15 +982,16 @@ impl<'lua> AnyUserData<'lua> {
|
|||
V: ToLua<'lua>,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 5)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0)?;
|
||||
lua.push_value(v.to_lua(lua)?)?;
|
||||
|
||||
// Multiple (extra) user values are emulated by storing them in a table
|
||||
protect_lua!(lua.state, 2, 0, |state| {
|
||||
protect_lua!(state, 2, 0, |state| {
|
||||
if getuservalue_table(state, -2) != ffi::LUA_TTABLE {
|
||||
// Create a new table to use as uservalue
|
||||
ffi::lua_pop(state, 1);
|
||||
|
@ -1016,14 +1020,15 @@ impl<'lua> AnyUserData<'lua> {
|
|||
V: FromLua<'lua>,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 4)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 4)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0)?;
|
||||
|
||||
// Multiple (extra) user values are emulated by storing them in a table
|
||||
protect_lua!(lua.state, 1, 1, |state| {
|
||||
protect_lua!(state, 1, 1, |state| {
|
||||
if getuservalue_table(state, -1) != ffi::LUA_TTABLE {
|
||||
ffi::lua_pushnil(state);
|
||||
return;
|
||||
|
@ -1050,13 +1055,14 @@ impl<'lua> AnyUserData<'lua> {
|
|||
}
|
||||
|
||||
fn get_raw_metatable(&self) -> Result<Table<'lua>> {
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let lua = self.0.lua;
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 3)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 3)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0)?;
|
||||
ffi::lua_getmetatable(lua.state, -1); // Checked that non-empty on the previous call
|
||||
ffi::lua_getmetatable(state, -1); // Checked that non-empty on the previous call
|
||||
Ok(Table(lua.pop_ref()))
|
||||
}
|
||||
}
|
||||
|
@ -1093,14 +1099,15 @@ impl<'lua> AnyUserData<'lua> {
|
|||
F: FnOnce(&'a UserDataCell<T>) -> Result<R>,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = lua.push_userdata_ref(&self.0)?;
|
||||
match type_id {
|
||||
Some(type_id) if type_id == TypeId::of::<T>() => {
|
||||
func(&*get_userdata::<UserDataCell<T>>(lua.state, -1))
|
||||
func(&*get_userdata::<UserDataCell<T>>(state, -1))
|
||||
}
|
||||
_ => Err(Error::UserDataTypeMismatch),
|
||||
}
|
||||
|
@ -1209,12 +1216,13 @@ impl<'lua> Serialize for AnyUserData<'lua> {
|
|||
S: Serializer,
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
let state = lua.state();
|
||||
let data = unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 3).map_err(ser::Error::custom)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 3).map_err(ser::Error::custom)?;
|
||||
|
||||
lua.push_userdata_ref(&self.0).map_err(ser::Error::custom)?;
|
||||
let ud = &*get_userdata::<UserDataCell<()>>(lua.state, -1);
|
||||
let ud = &*get_userdata::<UserDataCell<()>>(state, -1);
|
||||
ud.0.try_borrow()
|
||||
.map_err(|_| ser::Error::custom(Error::UserDataBorrowError))?
|
||||
};
|
||||
|
@ -1224,3 +1232,10 @@ impl<'lua> Serialize for AnyUserData<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_not_impl_any!(AnyUserData: Send);
|
||||
}
|
||||
|
|
|
@ -211,42 +211,43 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
{
|
||||
Box::new(move |lua, mut args| {
|
||||
if let Some(front) = args.pop_front() {
|
||||
let state = lua.state();
|
||||
let userdata = AnyUserData::from_lua(front, lua)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = lua.push_userdata_ref(&userdata.0)?;
|
||||
match type_id {
|
||||
Some(id) if id == TypeId::of::<T>() => {
|
||||
let ud = get_userdata_ref::<T>(lua.state)?;
|
||||
let ud = get_userdata_ref::<T>(state)?;
|
||||
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
|
||||
let ud = get_userdata_ref::<Rc<RefCell<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Rc<RefCell<T>>>(state)?;
|
||||
let ud = ud.try_borrow().map_err(|_| Error::UserDataBorrowError)?;
|
||||
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<Mutex<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<Mutex<T>>>(state)?;
|
||||
let ud = ud.try_lock().map_err(|_| Error::UserDataBorrowError)?;
|
||||
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state)?;
|
||||
let ud = ud.try_lock().ok_or(Error::UserDataBorrowError)?;
|
||||
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<RwLock<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<RwLock<T>>>(state)?;
|
||||
let ud = ud.try_read().map_err(|_| Error::UserDataBorrowError)?;
|
||||
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state)?;
|
||||
let ud = ud.try_read().ok_or(Error::UserDataBorrowError)?;
|
||||
method(lua, &ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
|
@ -272,49 +273,50 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
let method = RefCell::new(method);
|
||||
Box::new(move |lua, mut args| {
|
||||
if let Some(front) = args.pop_front() {
|
||||
let state = lua.state();
|
||||
let userdata = AnyUserData::from_lua(front, lua)?;
|
||||
let mut method = method
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| Error::RecursiveMutCallback)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = lua.push_userdata_ref(&userdata.0)?;
|
||||
match type_id {
|
||||
Some(id) if id == TypeId::of::<T>() => {
|
||||
let mut ud = get_userdata_mut::<T>(lua.state)?;
|
||||
let mut ud = get_userdata_mut::<T>(state)?;
|
||||
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
|
||||
let ud = get_userdata_mut::<Rc<RefCell<T>>>(lua.state)?;
|
||||
let ud = get_userdata_mut::<Rc<RefCell<T>>>(state)?;
|
||||
let mut ud = ud
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| Error::UserDataBorrowMutError)?;
|
||||
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
|
||||
let ud = get_userdata_mut::<Arc<Mutex<T>>>(lua.state)?;
|
||||
let ud = get_userdata_mut::<Arc<Mutex<T>>>(state)?;
|
||||
let mut ud =
|
||||
ud.try_lock().map_err(|_| Error::UserDataBorrowMutError)?;
|
||||
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(lua.state)?;
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(state)?;
|
||||
let mut ud = ud.try_lock().ok_or(Error::UserDataBorrowMutError)?;
|
||||
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
|
||||
let ud = get_userdata_mut::<Arc<RwLock<T>>>(lua.state)?;
|
||||
let ud = get_userdata_mut::<Arc<RwLock<T>>>(state)?;
|
||||
let mut ud =
|
||||
ud.try_write().map_err(|_| Error::UserDataBorrowMutError)?;
|
||||
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(lua.state)?;
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(state)?;
|
||||
let mut ud = ud.try_write().ok_or(Error::UserDataBorrowMutError)?;
|
||||
method(lua, &mut ud, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}
|
||||
|
@ -343,43 +345,43 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
Box::new(move |lua, mut args| {
|
||||
let fut_res = || {
|
||||
if let Some(front) = args.pop_front() {
|
||||
let state = lua.state();
|
||||
let userdata = AnyUserData::from_lua(front, lua)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(lua.state);
|
||||
check_stack(lua.state, 2)?;
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = lua.push_userdata_ref(&userdata.0)?;
|
||||
match type_id {
|
||||
Some(id) if id == TypeId::of::<T>() => {
|
||||
let ud = get_userdata_ref::<T>(lua.state)?;
|
||||
let ud = get_userdata_ref::<T>(state)?;
|
||||
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
|
||||
}
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
|
||||
let ud = get_userdata_ref::<Rc<RefCell<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Rc<RefCell<T>>>(state)?;
|
||||
let ud = ud.try_borrow().map_err(|_| Error::UserDataBorrowError)?;
|
||||
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<Mutex<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<Mutex<T>>>(state)?;
|
||||
let ud = ud.try_lock().map_err(|_| Error::UserDataBorrowError)?;
|
||||
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state)?;
|
||||
let ud = ud.try_lock().ok_or(Error::UserDataBorrowError)?;
|
||||
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<RwLock<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<RwLock<T>>>(state)?;
|
||||
let ud = ud.try_read().map_err(|_| Error::UserDataBorrowError)?;
|
||||
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
|
||||
let ud =
|
||||
get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(lua.state)?;
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state)?;
|
||||
let ud = ud.try_read().ok_or(Error::UserDataBorrowError)?;
|
||||
Ok(method(lua, ud.clone(), A::from_lua_multi(args, lua)?))
|
||||
}
|
||||
|
|
|
@ -357,3 +357,11 @@ pub trait FromLuaMulti<'lua>: Sized {
|
|||
/// any missing values are nil.
|
||||
fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod assertions {
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_not_impl_any!(Value: Send);
|
||||
static_assertions::assert_not_impl_any!(MultiValue: Send);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue