Merge branch 'master' of https://github.com/hack3ric/mlua
This commit is contained in:
commit
a6b178328d
|
@ -58,7 +58,7 @@ cc = { version = "1.0" }
|
||||||
pkg-config = { version = "0.3.17" }
|
pkg-config = { version = "0.3.17" }
|
||||||
lua-src = { version = ">= 544.0.0, < 550.0.0", optional = true }
|
lua-src = { version = ">= 544.0.0, < 550.0.0", optional = true }
|
||||||
luajit-src = { version = ">= 210.4.0, < 220.0.0", optional = true }
|
luajit-src = { version = ">= 210.4.0, < 220.0.0", optional = true }
|
||||||
luau0-src = { version = "0.3.2", optional = true }
|
luau0-src = { version = "0.3.6", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustyline = "9.0"
|
rustyline = "9.0"
|
||||||
|
|
|
@ -324,6 +324,12 @@ pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||||
lua_tolstring(L, i, ptr::null_mut())
|
lua_tolstring(L, i, ptr::null_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||||
|
lua_pushvalue(from, idx);
|
||||||
|
lua_xmove(from, to, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Debug API
|
// Debug API
|
||||||
//
|
//
|
||||||
|
|
|
@ -410,6 +410,12 @@ pub unsafe fn lua_tostring(L: *mut lua_State, i: c_int) -> *const c_char {
|
||||||
lua_tolstring(L, i, ptr::null_mut())
|
lua_tolstring(L, i, ptr::null_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||||
|
lua_pushvalue(from, idx);
|
||||||
|
lua_xmove(from, to, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Debug API
|
// Debug API
|
||||||
//
|
//
|
||||||
|
|
|
@ -434,6 +434,12 @@ pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) {
|
||||||
lua_pop(L, 1)
|
lua_pop(L, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||||
|
lua_pushvalue(from, idx);
|
||||||
|
lua_xmove(from, to, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Debug API
|
// Debug API
|
||||||
//
|
//
|
||||||
|
|
|
@ -455,6 +455,12 @@ pub unsafe fn lua_replace(L: *mut lua_State, idx: c_int) {
|
||||||
lua_pop(L, 1)
|
lua_pop(L, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn lua_xpush(from: *mut lua_State, to: *mut lua_State, idx: c_int) {
|
||||||
|
lua_pushvalue(from, idx);
|
||||||
|
lua_xmove(from, to, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub unsafe fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut c_void {
|
pub unsafe fn lua_newuserdata(L: *mut lua_State, sz: usize) -> *mut c_void {
|
||||||
lua_newuserdatauv(L, sz, 1)
|
lua_newuserdatauv(L, sz, 1)
|
||||||
|
|
|
@ -260,6 +260,7 @@ extern "C" {
|
||||||
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
|
// TODO: lua_encodepointer
|
||||||
pub fn lua_clock() -> c_double;
|
pub fn lua_clock() -> c_double;
|
||||||
|
pub fn lua_setuserdatatag(L: *mut lua_State, idx: c_int, tag: c_int);
|
||||||
pub fn lua_setuserdatadtor(
|
pub fn lua_setuserdatadtor(
|
||||||
L: *mut lua_State,
|
L: *mut lua_State,
|
||||||
tag: c_int,
|
tag: c_int,
|
||||||
|
@ -437,7 +438,12 @@ extern "C" {
|
||||||
pub fn lua_setupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
|
pub fn lua_setupvalue(L: *mut lua_State, funcindex: c_int, n: c_int) -> *const c_char;
|
||||||
|
|
||||||
pub fn lua_singlestep(L: *mut lua_State, enabled: c_int);
|
pub fn lua_singlestep(L: *mut lua_State, enabled: c_int);
|
||||||
pub fn lua_breakpoint(L: *mut lua_State, funcindex: c_int, line: c_int, enabled: c_int);
|
pub fn lua_breakpoint(
|
||||||
|
L: *mut lua_State,
|
||||||
|
funcindex: c_int,
|
||||||
|
line: c_int,
|
||||||
|
enabled: c_int,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
pub fn lua_getcoverage(
|
pub fn lua_getcoverage(
|
||||||
L: *mut lua_State,
|
L: *mut lua_State,
|
||||||
|
|
37
src/lua.rs
37
src/lua.rs
|
@ -25,7 +25,7 @@ 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, Integer, LightUserData, LuaRef, MaybeSend,
|
Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData, LuaRef, MaybeSend,
|
||||||
Number, RegistryKey,
|
Number, RegistryKey,
|
||||||
};
|
};
|
||||||
use crate::userdata::{AnyUserData, UserData, UserDataCell};
|
use crate::userdata::{AnyUserData, UserData, UserDataCell};
|
||||||
|
@ -111,6 +111,9 @@ pub(crate) struct ExtraData {
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
recycled_thread_cache: Vec<c_int>,
|
recycled_thread_cache: Vec<c_int>,
|
||||||
|
|
||||||
|
// Address of `WrappedFailure` metatable
|
||||||
|
wrapped_failure_mt_ptr: *const c_void,
|
||||||
|
|
||||||
// Index of `Option<Waker>` userdata on the ref thread
|
// Index of `Option<Waker>` userdata on the ref thread
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
ref_waker_idx: c_int,
|
ref_waker_idx: c_int,
|
||||||
|
@ -538,6 +541,13 @@ impl Lua {
|
||||||
"Error while creating ref thread",
|
"Error while creating ref thread",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let wrapped_failure_mt_ptr = {
|
||||||
|
get_gc_metatable::<WrappedFailure>(state);
|
||||||
|
let ptr = ffi::lua_topointer(state, -1);
|
||||||
|
ffi::lua_pop(state, 1);
|
||||||
|
ptr
|
||||||
|
};
|
||||||
|
|
||||||
// Create empty Waker slot on the ref thread
|
// Create empty Waker slot on the ref thread
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
let ref_waker_idx = {
|
let ref_waker_idx = {
|
||||||
|
@ -568,6 +578,7 @@ impl Lua {
|
||||||
multivalue_cache: Vec::with_capacity(MULTIVALUE_CACHE_SIZE),
|
multivalue_cache: Vec::with_capacity(MULTIVALUE_CACHE_SIZE),
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
recycled_thread_cache: Vec::new(),
|
recycled_thread_cache: Vec::new(),
|
||||||
|
wrapped_failure_mt_ptr,
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
ref_waker_idx,
|
ref_waker_idx,
|
||||||
#[cfg(not(feature = "luau"))]
|
#[cfg(not(feature = "luau"))]
|
||||||
|
@ -591,13 +602,13 @@ impl Lua {
|
||||||
"Error while storing extra data",
|
"Error while storing extra data",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Register `DestructedUserdataMT` type
|
// Register `DestructedUserdata` type
|
||||||
get_destructed_userdata_metatable(main_state);
|
get_destructed_userdata_metatable(main_state);
|
||||||
let destructed_mt_ptr = ffi::lua_topointer(main_state, -1);
|
let destructed_mt_ptr = ffi::lua_topointer(main_state, -1);
|
||||||
let destructed_mt_typeid = Some(TypeId::of::<DestructedUserdataMT>());
|
let destructed_ud_typeid = TypeId::of::<DestructedUserdata>();
|
||||||
(*extra.get())
|
(*extra.get())
|
||||||
.registered_userdata_mt
|
.registered_userdata_mt
|
||||||
.insert(destructed_mt_ptr, destructed_mt_typeid);
|
.insert(destructed_mt_ptr, Some(destructed_ud_typeid));
|
||||||
ffi::lua_pop(main_state, 1);
|
ffi::lua_pop(main_state, 1);
|
||||||
|
|
||||||
mlua_debug_assert!(
|
mlua_debug_assert!(
|
||||||
|
@ -2293,6 +2304,8 @@ impl Lua {
|
||||||
// Uses 2 stack spaces, does not call checkstack
|
// Uses 2 stack spaces, does not call checkstack
|
||||||
pub(crate) unsafe fn pop_value(&self) -> Value {
|
pub(crate) unsafe fn pop_value(&self) -> Value {
|
||||||
let state = self.state;
|
let state = self.state;
|
||||||
|
let extra = &mut *self.extra.get();
|
||||||
|
|
||||||
match ffi::lua_type(state, -1) {
|
match ffi::lua_type(state, -1) {
|
||||||
ffi::LUA_TNIL => {
|
ffi::LUA_TNIL => {
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
|
@ -2353,9 +2366,11 @@ impl Lua {
|
||||||
ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())),
|
ffi::LUA_TFUNCTION => Value::Function(Function(self.pop_ref())),
|
||||||
|
|
||||||
ffi::LUA_TUSERDATA => {
|
ffi::LUA_TUSERDATA => {
|
||||||
|
let wrapped_failure_mt_ptr = extra.wrapped_failure_mt_ptr;
|
||||||
// We must prevent interaction with userdata types other than UserData OR a WrappedError.
|
// We must prevent interaction with userdata types other than UserData OR a WrappedError.
|
||||||
// WrappedPanics are automatically resumed.
|
// WrappedPanics are automatically resumed.
|
||||||
match get_gc_userdata::<WrappedFailure>(state, -1).as_mut() {
|
match get_gc_userdata::<WrappedFailure>(state, -1, wrapped_failure_mt_ptr).as_mut()
|
||||||
|
{
|
||||||
Some(WrappedFailure::Error(err)) => {
|
Some(WrappedFailure::Error(err)) => {
|
||||||
let err = err.clone();
|
let err = err.clone();
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
|
@ -2394,12 +2409,6 @@ impl Lua {
|
||||||
"Lua instance passed Value created from a different main Lua state"
|
"Lua instance passed Value created from a different main Lua state"
|
||||||
);
|
);
|
||||||
let extra = &*self.extra.get();
|
let extra = &*self.extra.get();
|
||||||
#[cfg(not(feature = "luau"))]
|
|
||||||
{
|
|
||||||
ffi::lua_pushvalue(extra.ref_thread, lref.index);
|
|
||||||
ffi::lua_xmove(extra.ref_thread, self.state, 1);
|
|
||||||
}
|
|
||||||
#[cfg(feature = "luau")]
|
|
||||||
ffi::lua_xpush(extra.ref_thread, self.state, lref.index);
|
ffi::lua_xpush(extra.ref_thread, self.state, lref.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2578,7 +2587,7 @@ impl Lua {
|
||||||
|
|
||||||
let extra = &*self.extra.get();
|
let extra = &*self.extra.get();
|
||||||
match extra.registered_userdata_mt.get(&mt_ptr) {
|
match extra.registered_userdata_mt.get(&mt_ptr) {
|
||||||
Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdataMT>()) => {
|
Some(&type_id) if type_id == Some(TypeId::of::<DestructedUserdata>()) => {
|
||||||
Err(Error::UserDataDestructed)
|
Err(Error::UserDataDestructed)
|
||||||
}
|
}
|
||||||
Some(&type_id) => Ok(type_id),
|
Some(&type_id) => Ok(type_id),
|
||||||
|
@ -2952,14 +2961,14 @@ struct StateGuard<'a>(&'a mut LuaInner, *mut ffi::lua_State);
|
||||||
|
|
||||||
impl<'a> StateGuard<'a> {
|
impl<'a> StateGuard<'a> {
|
||||||
fn new(inner: &'a mut LuaInner, mut state: *mut ffi::lua_State) -> Self {
|
fn new(inner: &'a mut LuaInner, mut state: *mut ffi::lua_State) -> Self {
|
||||||
mem::swap(&mut (*inner).state, &mut state);
|
mem::swap(&mut inner.state, &mut state);
|
||||||
Self(inner, state)
|
Self(inner, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drop for StateGuard<'a> {
|
impl<'a> Drop for StateGuard<'a> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
mem::swap(&mut (*self.0).state, &mut self.1);
|
mem::swap(&mut self.0.state, &mut self.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ pub trait MaybeSend {}
|
||||||
#[cfg(not(feature = "send"))]
|
#[cfg(not(feature = "send"))]
|
||||||
impl<T> MaybeSend for T {}
|
impl<T> MaybeSend for T {}
|
||||||
|
|
||||||
pub(crate) struct DestructedUserdataMT;
|
pub(crate) struct DestructedUserdata;
|
||||||
|
|
||||||
/// An auto generated key into the Lua registry.
|
/// An auto generated key into the Lua registry.
|
||||||
///
|
///
|
||||||
|
|
66
src/util.rs
66
src/util.rs
|
@ -1,6 +1,7 @@
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
use std::os::raw::{c_char, c_int, c_void};
|
use std::os::raw::{c_char, c_int, c_void};
|
||||||
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
|
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -136,26 +137,21 @@ where
|
||||||
F: Fn(*mut ffi::lua_State) -> R,
|
F: Fn(*mut ffi::lua_State) -> R,
|
||||||
R: Copy,
|
R: Copy,
|
||||||
{
|
{
|
||||||
union URes<R: Copy> {
|
|
||||||
uninit: (),
|
|
||||||
init: R,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Params<F, R: Copy> {
|
struct Params<F, R: Copy> {
|
||||||
function: F,
|
function: F,
|
||||||
result: URes<R>,
|
result: MaybeUninit<R>,
|
||||||
nresults: c_int,
|
nresults: c_int,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
|
unsafe extern "C" fn do_call<F, R>(state: *mut ffi::lua_State) -> c_int
|
||||||
where
|
where
|
||||||
R: Copy,
|
|
||||||
F: Fn(*mut ffi::lua_State) -> R,
|
F: Fn(*mut ffi::lua_State) -> R,
|
||||||
|
R: Copy,
|
||||||
{
|
{
|
||||||
let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>;
|
let params = ffi::lua_touserdata(state, -1) as *mut Params<F, R>;
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
|
|
||||||
(*params).result.init = ((*params).function)(state);
|
(*params).result.write(((*params).function)(state));
|
||||||
|
|
||||||
if (*params).nresults == ffi::LUA_MULTRET {
|
if (*params).nresults == ffi::LUA_MULTRET {
|
||||||
ffi::lua_gettop(state)
|
ffi::lua_gettop(state)
|
||||||
|
@ -174,7 +170,7 @@ where
|
||||||
|
|
||||||
let mut params = Params {
|
let mut params = Params {
|
||||||
function: f,
|
function: f,
|
||||||
result: URes { uninit: () },
|
result: MaybeUninit::uninit(),
|
||||||
nresults,
|
nresults,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +181,7 @@ where
|
||||||
if ret == ffi::LUA_OK {
|
if ret == ffi::LUA_OK {
|
||||||
// `LUA_OK` is only returned when the `do_call` function has completed successfully, so
|
// `LUA_OK` is only returned when the `do_call` function has completed successfully, so
|
||||||
// `params.result` is definitely initialized.
|
// `params.result` is definitely initialized.
|
||||||
Ok(params.result.init)
|
Ok(params.result.assume_init())
|
||||||
} else {
|
} else {
|
||||||
Err(pop_error(state, ret))
|
Err(pop_error(state, ret))
|
||||||
}
|
}
|
||||||
|
@ -203,7 +199,7 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State, err_code: c_int) -> Error {
|
||||||
"pop_error called with non-error return code"
|
"pop_error called with non-error return code"
|
||||||
);
|
);
|
||||||
|
|
||||||
match get_gc_userdata::<WrappedFailure>(state, -1).as_mut() {
|
match get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_mut() {
|
||||||
Some(WrappedFailure::Error(err)) => {
|
Some(WrappedFailure::Error(err)) => {
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
err.clone()
|
err.clone()
|
||||||
|
@ -314,10 +310,7 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool) -> Result<()> {
|
pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool) -> Result<()> {
|
||||||
unsafe extern "C" fn destructor<T>(ud: *mut c_void) {
|
unsafe extern "C" fn destructor<T>(ud: *mut c_void) {
|
||||||
let ud = ud as *mut T;
|
ptr::drop_in_place(ud as *mut T);
|
||||||
if *(ud.offset(1) as *mut u8) == 0 {
|
|
||||||
ptr::drop_in_place(ud);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = mem::size_of::<T>() + 1;
|
let size = mem::size_of::<T>() + 1;
|
||||||
|
@ -329,7 +322,6 @@ pub unsafe fn push_userdata<T>(state: *mut ffi::lua_State, t: T, protect: bool)
|
||||||
ffi::lua_newuserdatadtor(state, size, destructor::<T>) as *mut T
|
ffi::lua_newuserdatadtor(state, size, destructor::<T>) as *mut T
|
||||||
};
|
};
|
||||||
ptr::write(ud, t);
|
ptr::write(ud, t);
|
||||||
*(ud.offset(1) as *mut u8) = 0; // Mark as not destructed
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -373,10 +365,12 @@ pub unsafe fn take_userdata<T>(state: *mut ffi::lua_State) -> T {
|
||||||
get_destructed_userdata_metatable(state);
|
get_destructed_userdata_metatable(state);
|
||||||
ffi::lua_setmetatable(state, -2);
|
ffi::lua_setmetatable(state, -2);
|
||||||
let ud = get_userdata::<T>(state, -1);
|
let ud = get_userdata::<T>(state, -1);
|
||||||
|
|
||||||
|
// Update userdata tag to disable destructor and mark as destructed
|
||||||
|
#[cfg(feature = "luau")]
|
||||||
|
ffi::lua_setuserdatatag(state, -1, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,16 +388,28 @@ pub unsafe fn push_gc_userdata<T: Any>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses 2 stack spaces, does not call checkstack
|
// Uses 2 stack spaces, does not call checkstack
|
||||||
pub unsafe fn get_gc_userdata<T: Any>(state: *mut ffi::lua_State, index: c_int) -> *mut T {
|
pub unsafe fn get_gc_userdata<T: Any>(
|
||||||
|
state: *mut ffi::lua_State,
|
||||||
|
index: c_int,
|
||||||
|
mt_ptr: *const c_void,
|
||||||
|
) -> *mut T {
|
||||||
let ud = ffi::lua_touserdata(state, index) as *mut T;
|
let ud = ffi::lua_touserdata(state, index) as *mut T;
|
||||||
if ud.is_null() || ffi::lua_getmetatable(state, index) == 0 {
|
if ud.is_null() || ffi::lua_getmetatable(state, index) == 0 {
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
get_gc_metatable::<T>(state);
|
if !mt_ptr.is_null() {
|
||||||
let res = ffi::lua_rawequal(state, -1, -2);
|
let ud_mt_ptr = ffi::lua_topointer(state, -1);
|
||||||
ffi::lua_pop(state, 2);
|
ffi::lua_pop(state, 1);
|
||||||
if res == 0 {
|
if !ptr::eq(ud_mt_ptr, mt_ptr) {
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get_gc_metatable::<T>(state);
|
||||||
|
let res = ffi::lua_rawequal(state, -1, -2);
|
||||||
|
ffi::lua_pop(state, 2);
|
||||||
|
if res == 0 {
|
||||||
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ud
|
ud
|
||||||
}
|
}
|
||||||
|
@ -679,7 +685,7 @@ pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if get_gc_userdata::<WrappedFailure>(state, -1).is_null() {
|
if get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).is_null() {
|
||||||
let s = ffi::luaL_tolstring(state, -1, ptr::null_mut());
|
let s = ffi::luaL_tolstring(state, -1, ptr::null_mut());
|
||||||
if ffi::lua_checkstack(state, ffi::LUA_TRACEBACK_STACK) != 0 {
|
if ffi::lua_checkstack(state, ffi::LUA_TRACEBACK_STACK) != 0 {
|
||||||
ffi::luaL_traceback(state, state, s, 0);
|
ffi::luaL_traceback(state, state, s, 0);
|
||||||
|
@ -706,7 +712,7 @@ pub unsafe extern "C" fn safe_pcall(state: *mut ffi::lua_State) -> c_int {
|
||||||
ffi::lua_gettop(state)
|
ffi::lua_gettop(state)
|
||||||
} else {
|
} else {
|
||||||
if let Some(WrappedFailure::Panic(_)) =
|
if let Some(WrappedFailure::Panic(_)) =
|
||||||
get_gc_userdata::<WrappedFailure>(state, -1).as_ref()
|
get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref()
|
||||||
{
|
{
|
||||||
ffi::lua_error(state);
|
ffi::lua_error(state);
|
||||||
}
|
}
|
||||||
|
@ -722,7 +728,7 @@ pub unsafe extern "C" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
|
||||||
ffi::luaL_checkstack(state, 2, ptr::null());
|
ffi::luaL_checkstack(state, 2, ptr::null());
|
||||||
|
|
||||||
if let Some(WrappedFailure::Panic(_)) =
|
if let Some(WrappedFailure::Panic(_)) =
|
||||||
get_gc_userdata::<WrappedFailure>(state, -1).as_ref()
|
get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref()
|
||||||
{
|
{
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
@ -752,7 +758,7 @@ pub unsafe extern "C" fn safe_xpcall(state: *mut ffi::lua_State) -> c_int {
|
||||||
ffi::lua_gettop(state) - 1
|
ffi::lua_gettop(state) - 1
|
||||||
} else {
|
} else {
|
||||||
if let Some(WrappedFailure::Panic(_)) =
|
if let Some(WrappedFailure::Panic(_)) =
|
||||||
get_gc_userdata::<WrappedFailure>(state, -1).as_ref()
|
get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref()
|
||||||
{
|
{
|
||||||
ffi::lua_error(state);
|
ffi::lua_error(state);
|
||||||
}
|
}
|
||||||
|
@ -836,7 +842,7 @@ pub unsafe fn init_error_registry(state: *mut ffi::lua_State) -> Result<()> {
|
||||||
callback_error(state, |_| {
|
callback_error(state, |_| {
|
||||||
check_stack(state, 3)?;
|
check_stack(state, 3)?;
|
||||||
|
|
||||||
let err_buf = match get_gc_userdata::<WrappedFailure>(state, -1).as_ref() {
|
let err_buf = match get_gc_userdata::<WrappedFailure>(state, -1, ptr::null()).as_ref() {
|
||||||
Some(WrappedFailure::Error(error)) => {
|
Some(WrappedFailure::Error(error)) => {
|
||||||
let err_buf_key = &ERROR_PRINT_BUFFER_KEY as *const u8 as *const c_void;
|
let err_buf_key = &ERROR_PRINT_BUFFER_KEY as *const u8 as *const c_void;
|
||||||
ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, err_buf_key);
|
ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, err_buf_key);
|
||||||
|
|
|
@ -239,7 +239,7 @@ impl<'a, 'lua> IntoIterator for &'a MultiValue<'lua> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
(&self.0).iter().rev()
|
self.0.iter().rev()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue