Remove `stack_guard` function and instead just use StackGuard directly
This commit is contained in:
parent
7b2f7a2932
commit
ee23f199f0
|
@ -170,9 +170,7 @@ fn create_registry_values(c: &mut Criterion) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_userdata(c: &mut Criterion) {
|
fn create_userdata(c: &mut Criterion) {
|
||||||
struct UserData {
|
struct UserData(i64);
|
||||||
i: i64,
|
|
||||||
}
|
|
||||||
impl LuaUserData for UserData {}
|
impl LuaUserData for UserData {}
|
||||||
|
|
||||||
c.bench_function("create userdata 10", |b| {
|
c.bench_function("create userdata 10", |b| {
|
||||||
|
@ -182,7 +180,7 @@ fn create_userdata(c: &mut Criterion) {
|
||||||
{
|
{
|
||||||
let table: LuaTable = lua.create_table().unwrap();
|
let table: LuaTable = lua.create_table().unwrap();
|
||||||
for i in 1..11 {
|
for i in 1..11 {
|
||||||
table.set(i, UserData { i }).unwrap();
|
table.set(i, UserData(i)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua
|
lua
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::os::raw::c_int;
|
||||||
use ffi;
|
use ffi;
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use util::{check_stack, check_stack_err, error_traceback, pop_error, protect_lua_closure,
|
use util::{check_stack, check_stack_err, error_traceback, pop_error, protect_lua_closure,
|
||||||
stack_guard};
|
StackGuard};
|
||||||
use types::LuaRef;
|
use types::LuaRef;
|
||||||
use value::{FromLuaMulti, MultiValue, ToLuaMulti};
|
use value::{FromLuaMulti, MultiValue, ToLuaMulti};
|
||||||
|
|
||||||
|
@ -63,31 +63,32 @@ impl<'lua> Function<'lua> {
|
||||||
/// ```
|
/// ```
|
||||||
pub fn call<A: ToLuaMulti<'lua>, R: FromLuaMulti<'lua>>(&self, args: A) -> Result<R> {
|
pub fn call<A: ToLuaMulti<'lua>, R: FromLuaMulti<'lua>>(&self, args: A) -> Result<R> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
|
||||||
stack_guard(lua.state, || {
|
|
||||||
let args = args.to_lua_multi(lua)?;
|
|
||||||
let nargs = args.len() as c_int;
|
|
||||||
check_stack_err(lua.state, nargs + 3)?;
|
|
||||||
|
|
||||||
ffi::lua_pushcfunction(lua.state, error_traceback);
|
let args = args.to_lua_multi(lua)?;
|
||||||
let stack_start = ffi::lua_gettop(lua.state);
|
let nargs = args.len() as c_int;
|
||||||
lua.push_ref(&self.0);
|
|
||||||
for arg in args {
|
unsafe {
|
||||||
lua.push_value(arg);
|
let _sg = StackGuard::new(lua.state);
|
||||||
}
|
check_stack_err(lua.state, nargs + 3)?;
|
||||||
let ret = ffi::lua_pcall(lua.state, nargs, ffi::LUA_MULTRET, stack_start);
|
|
||||||
if ret != ffi::LUA_OK {
|
ffi::lua_pushcfunction(lua.state, error_traceback);
|
||||||
return Err(pop_error(lua.state, ret));
|
let stack_start = ffi::lua_gettop(lua.state);
|
||||||
}
|
lua.push_ref(&self.0);
|
||||||
let nresults = ffi::lua_gettop(lua.state) - stack_start;
|
for arg in args {
|
||||||
let mut results = MultiValue::new();
|
lua.push_value(arg);
|
||||||
check_stack(lua.state, 2);
|
}
|
||||||
for _ in 0..nresults {
|
let ret = ffi::lua_pcall(lua.state, nargs, ffi::LUA_MULTRET, stack_start);
|
||||||
results.push_front(lua.pop_value());
|
if ret != ffi::LUA_OK {
|
||||||
}
|
return Err(pop_error(lua.state, ret));
|
||||||
ffi::lua_pop(lua.state, 1);
|
}
|
||||||
R::from_lua_multi(results, lua)
|
let nresults = ffi::lua_gettop(lua.state) - stack_start;
|
||||||
})
|
let mut results = MultiValue::new();
|
||||||
|
check_stack(lua.state, 2);
|
||||||
|
for _ in 0..nresults {
|
||||||
|
results.push_front(lua.pop_value());
|
||||||
|
}
|
||||||
|
ffi::lua_pop(lua.state, 1);
|
||||||
|
R::from_lua_multi(results, lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,28 +145,28 @@ impl<'lua> Function<'lua> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
|
|
||||||
|
let args = args.to_lua_multi(lua)?;
|
||||||
|
let nargs = args.len() as c_int;
|
||||||
|
|
||||||
|
if nargs + 2 > ffi::LUA_MAX_UPVALUES {
|
||||||
|
return Err(Error::BindError);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
let args = args.to_lua_multi(lua)?;
|
check_stack_err(lua.state, nargs + 5)?;
|
||||||
let nargs = args.len() as c_int;
|
lua.push_ref(&self.0);
|
||||||
|
ffi::lua_pushinteger(lua.state, nargs as ffi::lua_Integer);
|
||||||
|
for arg in args {
|
||||||
|
lua.push_value(arg);
|
||||||
|
}
|
||||||
|
|
||||||
if nargs + 2 > ffi::LUA_MAX_UPVALUES {
|
protect_lua_closure(lua.state, nargs + 2, 1, |state| {
|
||||||
return Err(Error::BindError);
|
ffi::lua_pushcclosure(state, bind_call_impl, nargs + 2);
|
||||||
}
|
})?;
|
||||||
|
|
||||||
check_stack_err(lua.state, nargs + 5)?;
|
Ok(Function(lua.pop_ref()))
|
||||||
lua.push_ref(&self.0);
|
|
||||||
ffi::lua_pushinteger(lua.state, nargs as ffi::lua_Integer);
|
|
||||||
for arg in args {
|
|
||||||
lua.push_value(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
protect_lua_closure(lua.state, nargs + 2, 1, |state| {
|
|
||||||
ffi::lua_pushcclosure(state, bind_call_impl, nargs + 2);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(Function(lua.pop_ref()))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
566
src/lua.rs
566
src/lua.rs
|
@ -14,8 +14,8 @@ use ffi;
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use util::{callback_error, check_stack, check_stack_err, gc_guard, get_userdata,
|
use util::{callback_error, check_stack, check_stack_err, gc_guard, get_userdata,
|
||||||
get_wrapped_error, init_error_metatables, pop_error, protect_lua, protect_lua_closure,
|
get_wrapped_error, init_error_metatables, pop_error, protect_lua, protect_lua_closure,
|
||||||
push_string, push_userdata, push_wrapped_error, safe_pcall, safe_xpcall, stack_guard,
|
push_string, push_userdata, push_wrapped_error, safe_pcall, safe_xpcall, take_userdata,
|
||||||
take_userdata, userdata_destructor};
|
userdata_destructor, StackGuard};
|
||||||
use value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
use value::{FromLua, FromLuaMulti, MultiValue, Nil, ToLua, ToLuaMulti, Value};
|
||||||
use types::{Callback, Integer, LightUserData, LuaRef, Number, RefType, RegistryKey};
|
use types::{Callback, Integer, LightUserData, LuaRef, Number, RefType, RegistryKey};
|
||||||
use string::String;
|
use string::String;
|
||||||
|
@ -102,34 +102,33 @@ impl Lua {
|
||||||
/// Equivalent to Lua's `load` function.
|
/// Equivalent to Lua's `load` function.
|
||||||
pub fn load(&self, source: &str, name: Option<&str>) -> Result<Function> {
|
pub fn load(&self, source: &str, name: Option<&str>) -> Result<Function> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 1);
|
check_stack(self.state, 1);
|
||||||
|
|
||||||
match if let Some(name) = name {
|
match if let Some(name) = name {
|
||||||
let name =
|
let name =
|
||||||
CString::new(name.to_owned()).map_err(|e| Error::ToLuaConversionError {
|
CString::new(name.to_owned()).map_err(|e| Error::ToLuaConversionError {
|
||||||
from: "&str",
|
from: "&str",
|
||||||
to: "string",
|
to: "string",
|
||||||
message: Some(e.to_string()),
|
message: Some(e.to_string()),
|
||||||
})?;
|
})?;
|
||||||
ffi::luaL_loadbuffer(
|
ffi::luaL_loadbuffer(
|
||||||
self.state,
|
self.state,
|
||||||
source.as_ptr() as *const c_char,
|
source.as_ptr() as *const c_char,
|
||||||
source.len(),
|
source.len(),
|
||||||
name.as_ptr(),
|
name.as_ptr(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ffi::luaL_loadbuffer(
|
ffi::luaL_loadbuffer(
|
||||||
self.state,
|
self.state,
|
||||||
source.as_ptr() as *const c_char,
|
source.as_ptr() as *const c_char,
|
||||||
source.len(),
|
source.len(),
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
ffi::LUA_OK => Ok(Function(self.pop_ref())),
|
ffi::LUA_OK => Ok(Function(self.pop_ref())),
|
||||||
err => Err(pop_error(self.state, err)),
|
err => Err(pop_error(self.state, err)),
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,26 +166,24 @@ impl Lua {
|
||||||
/// Pass a `&str` slice to Lua, creating and returning an interned Lua string.
|
/// Pass a `&str` slice to Lua, creating and returning an interned Lua string.
|
||||||
pub fn create_string(&self, s: &str) -> Result<String> {
|
pub fn create_string(&self, s: &str) -> Result<String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 4);
|
check_stack(self.state, 4);
|
||||||
push_string(self.state, s)?;
|
push_string(self.state, s)?;
|
||||||
Ok(String(self.pop_ref()))
|
Ok(String(self.pop_ref()))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and returns a new table.
|
/// Creates and returns a new table.
|
||||||
pub fn create_table(&self) -> Result<Table> {
|
pub fn create_table(&self) -> Result<Table> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 3);
|
check_stack(self.state, 3);
|
||||||
unsafe extern "C" fn new_table(state: *mut ffi::lua_State) -> c_int {
|
unsafe extern "C" fn new_table(state: *mut ffi::lua_State) -> c_int {
|
||||||
ffi::lua_newtable(state);
|
ffi::lua_newtable(state);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
protect_lua(self.state, 0, new_table)?;
|
protect_lua(self.state, 0, new_table)?;
|
||||||
Ok(Table(self.pop_ref()))
|
Ok(Table(self.pop_ref()))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,25 +195,25 @@ impl Lua {
|
||||||
I: IntoIterator<Item = (K, V)>,
|
I: IntoIterator<Item = (K, V)>,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 5);
|
check_stack(self.state, 5);
|
||||||
unsafe extern "C" fn new_table(state: *mut ffi::lua_State) -> c_int {
|
|
||||||
ffi::lua_newtable(state);
|
unsafe extern "C" fn new_table(state: *mut ffi::lua_State) -> c_int {
|
||||||
|
ffi::lua_newtable(state);
|
||||||
|
1
|
||||||
|
}
|
||||||
|
protect_lua(self.state, 0, new_table)?;
|
||||||
|
|
||||||
|
for (k, v) in cont {
|
||||||
|
self.push_value(k.to_lua(self)?);
|
||||||
|
self.push_value(v.to_lua(self)?);
|
||||||
|
unsafe extern "C" fn raw_set(state: *mut ffi::lua_State) -> c_int {
|
||||||
|
ffi::lua_rawset(state, -3);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
protect_lua(self.state, 0, new_table)?;
|
protect_lua(self.state, 3, raw_set)?;
|
||||||
|
}
|
||||||
for (k, v) in cont {
|
Ok(Table(self.pop_ref()))
|
||||||
self.push_value(k.to_lua(self)?);
|
|
||||||
self.push_value(v.to_lua(self)?);
|
|
||||||
unsafe extern "C" fn raw_set(state: *mut ffi::lua_State) -> c_int {
|
|
||||||
ffi::lua_rawset(state, -3);
|
|
||||||
1
|
|
||||||
}
|
|
||||||
protect_lua(self.state, 3, raw_set)?;
|
|
||||||
}
|
|
||||||
Ok(Table(self.pop_ref()))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,16 +319,15 @@ impl Lua {
|
||||||
/// Equivalent to `coroutine.create`.
|
/// Equivalent to `coroutine.create`.
|
||||||
pub fn create_thread<'lua>(&'lua self, func: Function<'lua>) -> Result<Thread<'lua>> {
|
pub fn create_thread<'lua>(&'lua self, func: Function<'lua>) -> Result<Thread<'lua>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, move || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 2);
|
check_stack(self.state, 2);
|
||||||
|
|
||||||
let thread_state =
|
let thread_state =
|
||||||
protect_lua_closure(self.state, 0, 1, |state| ffi::lua_newthread(state))?;
|
protect_lua_closure(self.state, 0, 1, |state| ffi::lua_newthread(state))?;
|
||||||
self.push_ref(&func.0);
|
self.push_ref(&func.0);
|
||||||
ffi::lua_xmove(self.state, thread_state, 1);
|
ffi::lua_xmove(self.state, thread_state, 1);
|
||||||
|
|
||||||
Ok(Thread(self.pop_ref()))
|
Ok(Thread(self.pop_ref()))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,11 +342,10 @@ impl Lua {
|
||||||
/// Returns a handle to the global environment.
|
/// Returns a handle to the global environment.
|
||||||
pub fn globals(&self) -> Table {
|
pub fn globals(&self) -> Table {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, move || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 2);
|
check_stack(self.state, 2);
|
||||||
ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
|
ffi::lua_rawgeti(self.state, ffi::LUA_REGISTRYINDEX, ffi::LUA_RIDX_GLOBALS);
|
||||||
Table(self.pop_ref())
|
Table(self.pop_ref())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,23 +387,22 @@ impl Lua {
|
||||||
match v {
|
match v {
|
||||||
Value::String(s) => Ok(s),
|
Value::String(s) => Ok(s),
|
||||||
v => unsafe {
|
v => unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 4);
|
check_stack(self.state, 4);
|
||||||
let ty = v.type_name();
|
|
||||||
self.push_value(v);
|
let ty = v.type_name();
|
||||||
let s = protect_lua_closure(self.state, 1, 1, |state| {
|
self.push_value(v);
|
||||||
ffi::lua_tostring(state, -1)
|
let s =
|
||||||
})?;
|
protect_lua_closure(self.state, 1, 1, |state| ffi::lua_tostring(state, -1))?;
|
||||||
if s.is_null() {
|
if s.is_null() {
|
||||||
Err(Error::FromLuaConversionError {
|
Err(Error::FromLuaConversionError {
|
||||||
from: ty,
|
from: ty,
|
||||||
to: "String",
|
to: "String",
|
||||||
message: Some("expected string or number".to_string()),
|
message: Some("expected string or number".to_string()),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(String(self.pop_ref()))
|
Ok(String(self.pop_ref()))
|
||||||
}
|
}
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -421,22 +415,22 @@ impl Lua {
|
||||||
match v {
|
match v {
|
||||||
Value::Integer(i) => Ok(i),
|
Value::Integer(i) => Ok(i),
|
||||||
v => unsafe {
|
v => unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 2);
|
check_stack(self.state, 2);
|
||||||
let ty = v.type_name();
|
|
||||||
self.push_value(v);
|
let ty = v.type_name();
|
||||||
let mut isint = 0;
|
self.push_value(v);
|
||||||
let i = ffi::lua_tointegerx(self.state, -1, &mut isint);
|
let mut isint = 0;
|
||||||
if isint == 0 {
|
let i = ffi::lua_tointegerx(self.state, -1, &mut isint);
|
||||||
Err(Error::FromLuaConversionError {
|
if isint == 0 {
|
||||||
from: ty,
|
Err(Error::FromLuaConversionError {
|
||||||
to: "integer",
|
from: ty,
|
||||||
message: None,
|
to: "integer",
|
||||||
})
|
message: None,
|
||||||
} else {
|
})
|
||||||
Ok(i)
|
} else {
|
||||||
}
|
Ok(i)
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,22 +443,22 @@ impl Lua {
|
||||||
match v {
|
match v {
|
||||||
Value::Number(n) => Ok(n),
|
Value::Number(n) => Ok(n),
|
||||||
v => unsafe {
|
v => unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 2);
|
check_stack(self.state, 2);
|
||||||
let ty = v.type_name();
|
|
||||||
self.push_value(v);
|
let ty = v.type_name();
|
||||||
let mut isnum = 0;
|
self.push_value(v);
|
||||||
let n = ffi::lua_tonumberx(self.state, -1, &mut isnum);
|
let mut isnum = 0;
|
||||||
if isnum == 0 {
|
let n = ffi::lua_tonumberx(self.state, -1, &mut isnum);
|
||||||
Err(Error::FromLuaConversionError {
|
if isnum == 0 {
|
||||||
from: ty,
|
Err(Error::FromLuaConversionError {
|
||||||
to: "number",
|
from: ty,
|
||||||
message: Some("number or string coercible to number".to_string()),
|
to: "number",
|
||||||
})
|
message: Some("number or string coercible to number".to_string()),
|
||||||
} else {
|
})
|
||||||
Ok(n)
|
} else {
|
||||||
}
|
Ok(n)
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,18 +496,17 @@ impl Lua {
|
||||||
t: T,
|
t: T,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 5);
|
check_stack(self.state, 5);
|
||||||
|
|
||||||
push_string(self.state, name)?;
|
push_string(self.state, name)?;
|
||||||
self.push_value(t.to_lua(self)?);
|
self.push_value(t.to_lua(self)?);
|
||||||
|
|
||||||
unsafe extern "C" fn set_registry(state: *mut ffi::lua_State) -> c_int {
|
unsafe extern "C" fn set_registry(state: *mut ffi::lua_State) -> c_int {
|
||||||
ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX);
|
ffi::lua_rawset(state, ffi::LUA_REGISTRYINDEX);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
protect_lua(self.state, 2, set_registry)
|
protect_lua(self.state, 2, set_registry)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,18 +518,17 @@ impl Lua {
|
||||||
/// [`set_named_registry_value`]: #method.set_named_registry_value
|
/// [`set_named_registry_value`]: #method.set_named_registry_value
|
||||||
pub fn named_registry_value<'lua, T: FromLua<'lua>>(&'lua self, name: &str) -> Result<T> {
|
pub fn named_registry_value<'lua, T: FromLua<'lua>>(&'lua self, name: &str) -> Result<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 4);
|
check_stack(self.state, 4);
|
||||||
|
|
||||||
push_string(self.state, name)?;
|
push_string(self.state, name)?;
|
||||||
unsafe extern "C" fn get_registry(state: *mut ffi::lua_State) -> c_int {
|
unsafe extern "C" fn get_registry(state: *mut ffi::lua_State) -> c_int {
|
||||||
ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
|
ffi::lua_rawget(state, ffi::LUA_REGISTRYINDEX);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
protect_lua(self.state, 1, get_registry)?;
|
protect_lua(self.state, 1, get_registry)?;
|
||||||
|
|
||||||
T::from_lua(self.pop_value(), self)
|
T::from_lua(self.pop_value(), self)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,18 +547,17 @@ impl Lua {
|
||||||
/// state.
|
/// state.
|
||||||
pub fn create_registry_value<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result<RegistryKey> {
|
pub fn create_registry_value<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result<RegistryKey> {
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 2);
|
check_stack(self.state, 2);
|
||||||
|
|
||||||
self.push_value(t.to_lua(self)?);
|
self.push_value(t.to_lua(self)?);
|
||||||
let registry_id = gc_guard(self.state, || {
|
let registry_id = gc_guard(self.state, || {
|
||||||
ffi::luaL_ref(self.state, ffi::LUA_REGISTRYINDEX)
|
ffi::luaL_ref(self.state, ffi::LUA_REGISTRYINDEX)
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(RegistryKey {
|
Ok(RegistryKey {
|
||||||
registry_id,
|
registry_id,
|
||||||
unref_list: (*self.extra()).registry_unref_list.clone(),
|
unref_list: (*self.extra()).registry_unref_list.clone(),
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,15 +574,15 @@ impl Lua {
|
||||||
return Err(Error::MismatchedRegistryKey);
|
return Err(Error::MismatchedRegistryKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_guard(self.state, || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 2);
|
check_stack(self.state, 2);
|
||||||
ffi::lua_rawgeti(
|
|
||||||
self.state,
|
ffi::lua_rawgeti(
|
||||||
ffi::LUA_REGISTRYINDEX,
|
self.state,
|
||||||
key.registry_id as ffi::lua_Integer,
|
ffi::LUA_REGISTRYINDEX,
|
||||||
);
|
key.registry_id as ffi::lua_Integer,
|
||||||
T::from_lua(self.pop_value(), self)
|
);
|
||||||
})
|
T::from_lua(self.pop_value(), self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,112 +874,111 @@ impl Lua {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_guard(self.state, move || {
|
if let Some(table_id) = (*self.extra()).registered_userdata.get(&TypeId::of::<T>()) {
|
||||||
if let Some(table_id) = (*self.extra()).registered_userdata.get(&TypeId::of::<T>()) {
|
return Ok(*table_id);
|
||||||
return Ok(*table_id);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
check_stack(self.state, 6);
|
let _sg = StackGuard::new(self.state);
|
||||||
|
check_stack(self.state, 6);
|
||||||
|
|
||||||
let mut methods = UserDataMethods {
|
let mut methods = UserDataMethods {
|
||||||
methods: HashMap::new(),
|
methods: HashMap::new(),
|
||||||
meta_methods: HashMap::new(),
|
meta_methods: HashMap::new(),
|
||||||
_type: PhantomData,
|
_type: PhantomData,
|
||||||
};
|
};
|
||||||
T::add_methods(&mut methods);
|
T::add_methods(&mut methods);
|
||||||
|
|
||||||
|
protect_lua_closure(self.state, 0, 1, |state| {
|
||||||
|
ffi::lua_newtable(state);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let has_methods = !methods.methods.is_empty();
|
||||||
|
|
||||||
|
if has_methods {
|
||||||
|
push_string(self.state, "__index")?;
|
||||||
protect_lua_closure(self.state, 0, 1, |state| {
|
protect_lua_closure(self.state, 0, 1, |state| {
|
||||||
ffi::lua_newtable(state);
|
ffi::lua_newtable(state);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let has_methods = !methods.methods.is_empty();
|
for (k, m) in methods.methods {
|
||||||
|
push_string(self.state, &k)?;
|
||||||
if has_methods {
|
self.push_value(Value::Function(self.create_callback_function(m)?));
|
||||||
push_string(self.state, "__index")?;
|
|
||||||
protect_lua_closure(self.state, 0, 1, |state| {
|
|
||||||
ffi::lua_newtable(state);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for (k, m) in methods.methods {
|
|
||||||
push_string(self.state, &k)?;
|
|
||||||
self.push_value(Value::Function(self.create_callback_function(m)?));
|
|
||||||
protect_lua_closure(self.state, 3, 1, |state| {
|
|
||||||
ffi::lua_rawset(state, -3);
|
|
||||||
})?;
|
|
||||||
}
|
|
||||||
|
|
||||||
protect_lua_closure(self.state, 3, 1, |state| {
|
protect_lua_closure(self.state, 3, 1, |state| {
|
||||||
ffi::lua_rawset(state, -3);
|
ffi::lua_rawset(state, -3);
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k, m) in methods.meta_methods {
|
protect_lua_closure(self.state, 3, 1, |state| {
|
||||||
if k == MetaMethod::Index && has_methods {
|
ffi::lua_rawset(state, -3);
|
||||||
push_string(self.state, "__index")?;
|
})?;
|
||||||
ffi::lua_pushvalue(self.state, -1);
|
}
|
||||||
ffi::lua_gettable(self.state, -3);
|
|
||||||
self.push_value(Value::Function(self.create_callback_function(m)?));
|
|
||||||
protect_lua_closure(self.state, 2, 1, |state| {
|
|
||||||
ffi::lua_pushcclosure(state, meta_index_impl, 2);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
protect_lua_closure(self.state, 3, 1, |state| {
|
for (k, m) in methods.meta_methods {
|
||||||
ffi::lua_rawset(state, -3);
|
if k == MetaMethod::Index && has_methods {
|
||||||
})?;
|
push_string(self.state, "__index")?;
|
||||||
} else {
|
ffi::lua_pushvalue(self.state, -1);
|
||||||
let name = match k {
|
ffi::lua_gettable(self.state, -3);
|
||||||
MetaMethod::Add => "__add",
|
self.push_value(Value::Function(self.create_callback_function(m)?));
|
||||||
MetaMethod::Sub => "__sub",
|
protect_lua_closure(self.state, 2, 1, |state| {
|
||||||
MetaMethod::Mul => "__mul",
|
ffi::lua_pushcclosure(state, meta_index_impl, 2);
|
||||||
MetaMethod::Div => "__div",
|
})?;
|
||||||
MetaMethod::Mod => "__mod",
|
|
||||||
MetaMethod::Pow => "__pow",
|
protect_lua_closure(self.state, 3, 1, |state| {
|
||||||
MetaMethod::Unm => "__unm",
|
ffi::lua_rawset(state, -3);
|
||||||
MetaMethod::IDiv => "__idiv",
|
})?;
|
||||||
MetaMethod::BAnd => "__band",
|
} else {
|
||||||
MetaMethod::BOr => "__bor",
|
let name = match k {
|
||||||
MetaMethod::BXor => "__bxor",
|
MetaMethod::Add => "__add",
|
||||||
MetaMethod::BNot => "__bnot",
|
MetaMethod::Sub => "__sub",
|
||||||
MetaMethod::Shl => "__shl",
|
MetaMethod::Mul => "__mul",
|
||||||
MetaMethod::Shr => "__shr",
|
MetaMethod::Div => "__div",
|
||||||
MetaMethod::Concat => "__concat",
|
MetaMethod::Mod => "__mod",
|
||||||
MetaMethod::Len => "__len",
|
MetaMethod::Pow => "__pow",
|
||||||
MetaMethod::Eq => "__eq",
|
MetaMethod::Unm => "__unm",
|
||||||
MetaMethod::Lt => "__lt",
|
MetaMethod::IDiv => "__idiv",
|
||||||
MetaMethod::Le => "__le",
|
MetaMethod::BAnd => "__band",
|
||||||
MetaMethod::Index => "__index",
|
MetaMethod::BOr => "__bor",
|
||||||
MetaMethod::NewIndex => "__newindex",
|
MetaMethod::BXor => "__bxor",
|
||||||
MetaMethod::Call => "__call",
|
MetaMethod::BNot => "__bnot",
|
||||||
MetaMethod::ToString => "__tostring",
|
MetaMethod::Shl => "__shl",
|
||||||
};
|
MetaMethod::Shr => "__shr",
|
||||||
push_string(self.state, name)?;
|
MetaMethod::Concat => "__concat",
|
||||||
self.push_value(Value::Function(self.create_callback_function(m)?));
|
MetaMethod::Len => "__len",
|
||||||
protect_lua_closure(self.state, 3, 1, |state| {
|
MetaMethod::Eq => "__eq",
|
||||||
ffi::lua_rawset(state, -3);
|
MetaMethod::Lt => "__lt",
|
||||||
})?;
|
MetaMethod::Le => "__le",
|
||||||
}
|
MetaMethod::Index => "__index",
|
||||||
|
MetaMethod::NewIndex => "__newindex",
|
||||||
|
MetaMethod::Call => "__call",
|
||||||
|
MetaMethod::ToString => "__tostring",
|
||||||
|
};
|
||||||
|
push_string(self.state, name)?;
|
||||||
|
self.push_value(Value::Function(self.create_callback_function(m)?));
|
||||||
|
protect_lua_closure(self.state, 3, 1, |state| {
|
||||||
|
ffi::lua_rawset(state, -3);
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
push_string(self.state, "__gc")?;
|
push_string(self.state, "__gc")?;
|
||||||
ffi::lua_pushcfunction(self.state, userdata_destructor::<RefCell<T>>);
|
ffi::lua_pushcfunction(self.state, userdata_destructor::<RefCell<T>>);
|
||||||
protect_lua_closure(self.state, 3, 1, |state| {
|
protect_lua_closure(self.state, 3, 1, |state| {
|
||||||
ffi::lua_rawset(state, -3);
|
ffi::lua_rawset(state, -3);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
push_string(self.state, "__metatable")?;
|
push_string(self.state, "__metatable")?;
|
||||||
ffi::lua_pushboolean(self.state, 0);
|
ffi::lua_pushboolean(self.state, 0);
|
||||||
protect_lua_closure(self.state, 3, 1, |state| {
|
protect_lua_closure(self.state, 3, 1, |state| {
|
||||||
ffi::lua_rawset(state, -3);
|
ffi::lua_rawset(state, -3);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let id = gc_guard(self.state, || {
|
let id = gc_guard(self.state, || {
|
||||||
ffi::luaL_ref(self.state, ffi::LUA_REGISTRYINDEX)
|
ffi::luaL_ref(self.state, ffi::LUA_REGISTRYINDEX)
|
||||||
});
|
});
|
||||||
(*self.extra())
|
(*self.extra())
|
||||||
.registered_userdata
|
.registered_userdata
|
||||||
.insert(TypeId::of::<T>(), id);
|
.insert(TypeId::of::<T>(), id);
|
||||||
Ok(id)
|
Ok(id)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_lua(load_debug: bool) -> Lua {
|
unsafe fn create_lua(load_debug: bool) -> Lua {
|
||||||
|
@ -1125,24 +1115,23 @@ impl Lua {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, move || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 4);
|
check_stack(self.state, 4);
|
||||||
|
|
||||||
push_userdata::<Callback>(self.state, func)?;
|
push_userdata::<Callback>(self.state, func)?;
|
||||||
|
|
||||||
ffi::lua_pushlightuserdata(
|
ffi::lua_pushlightuserdata(
|
||||||
self.state,
|
self.state,
|
||||||
&FUNCTION_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void,
|
&FUNCTION_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||||
);
|
);
|
||||||
ffi::lua_rawget(self.state, ffi::LUA_REGISTRYINDEX);
|
ffi::lua_rawget(self.state, ffi::LUA_REGISTRYINDEX);
|
||||||
ffi::lua_setmetatable(self.state, -2);
|
ffi::lua_setmetatable(self.state, -2);
|
||||||
|
|
||||||
protect_lua_closure(self.state, 1, 1, |state| {
|
protect_lua_closure(self.state, 1, 1, |state| {
|
||||||
ffi::lua_pushcclosure(state, callback_call_impl, 1);
|
ffi::lua_pushcclosure(state, callback_call_impl, 1);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(Function(self.pop_ref()))
|
Ok(Function(self.pop_ref()))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,21 +1140,20 @@ impl Lua {
|
||||||
T: UserData,
|
T: UserData,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(self.state, move || {
|
let _sg = StackGuard::new(self.state);
|
||||||
check_stack(self.state, 4);
|
check_stack(self.state, 4);
|
||||||
|
|
||||||
push_userdata::<RefCell<T>>(self.state, RefCell::new(data))?;
|
push_userdata::<RefCell<T>>(self.state, RefCell::new(data))?;
|
||||||
|
|
||||||
ffi::lua_rawgeti(
|
ffi::lua_rawgeti(
|
||||||
self.state,
|
self.state,
|
||||||
ffi::LUA_REGISTRYINDEX,
|
ffi::LUA_REGISTRYINDEX,
|
||||||
self.userdata_metatable::<T>()? as ffi::lua_Integer,
|
self.userdata_metatable::<T>()? as ffi::lua_Integer,
|
||||||
);
|
);
|
||||||
|
|
||||||
ffi::lua_setmetatable(self.state, -2);
|
ffi::lua_setmetatable(self.state, -2);
|
||||||
|
|
||||||
Ok(AnyUserData(self.pop_ref()))
|
Ok(AnyUserData(self.pop_ref()))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1290,19 +1278,18 @@ impl<'scope> Scope<'scope> {
|
||||||
let f_destruct = f.0.clone();
|
let f_destruct = f.0.clone();
|
||||||
destructors.push(Box::new(move || {
|
destructors.push(Box::new(move || {
|
||||||
let state = f_destruct.lua.state;
|
let state = f_destruct.lua.state;
|
||||||
stack_guard(state, || {
|
let _sg = StackGuard::new(state);
|
||||||
check_stack(state, 2);
|
check_stack(state, 2);
|
||||||
f_destruct.lua.push_ref(&f_destruct);
|
f_destruct.lua.push_ref(&f_destruct);
|
||||||
|
|
||||||
ffi::lua_getupvalue(state, -1, 1);
|
ffi::lua_getupvalue(state, -1, 1);
|
||||||
let ud = take_userdata::<Callback>(state);
|
let ud = take_userdata::<Callback>(state);
|
||||||
|
|
||||||
ffi::lua_pushnil(state);
|
ffi::lua_pushnil(state);
|
||||||
ffi::lua_setupvalue(state, -2, 1);
|
ffi::lua_setupvalue(state, -2, 1);
|
||||||
|
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
Box::new(ud)
|
Box::new(ud)
|
||||||
})
|
|
||||||
}));
|
}));
|
||||||
Ok(f)
|
Ok(f)
|
||||||
}
|
}
|
||||||
|
@ -1348,11 +1335,10 @@ impl<'scope> Scope<'scope> {
|
||||||
let u_destruct = u.0.clone();
|
let u_destruct = u.0.clone();
|
||||||
destructors.push(Box::new(move || {
|
destructors.push(Box::new(move || {
|
||||||
let state = u_destruct.lua.state;
|
let state = u_destruct.lua.state;
|
||||||
stack_guard(state, || {
|
let _sg = StackGuard::new(state);
|
||||||
check_stack(state, 1);
|
check_stack(state, 1);
|
||||||
u_destruct.lua.push_ref(&u_destruct);
|
u_destruct.lua.push_ref(&u_destruct);
|
||||||
Box::new(take_userdata::<RefCell<T>>(state))
|
Box::new(take_userdata::<RefCell<T>>(state))
|
||||||
})
|
|
||||||
}));
|
}));
|
||||||
Ok(u)
|
Ok(u)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{slice, str};
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use util::{check_stack, stack_guard};
|
use util::{check_stack, StackGuard};
|
||||||
use types::LuaRef;
|
use types::LuaRef;
|
||||||
|
|
||||||
/// Handle to an internal Lua string.
|
/// Handle to an internal Lua string.
|
||||||
|
@ -69,21 +69,21 @@ impl<'lua> String<'lua> {
|
||||||
pub fn as_bytes_with_nul(&self) -> &[u8] {
|
pub fn as_bytes_with_nul(&self) -> &[u8] {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 1);
|
check_stack(lua.state, 1);
|
||||||
lua.push_ref(&self.0);
|
|
||||||
rlua_assert!(
|
|
||||||
ffi::lua_type(lua.state, -1) == ffi::LUA_TSTRING,
|
|
||||||
"string ref is not string type"
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut size = 0;
|
lua.push_ref(&self.0);
|
||||||
// This will not trigger a 'm' error, because the reference is guaranteed to be of
|
rlua_assert!(
|
||||||
// string type
|
ffi::lua_type(lua.state, -1) == ffi::LUA_TSTRING,
|
||||||
let data = ffi::lua_tolstring(lua.state, -1, &mut size);
|
"string ref is not string type"
|
||||||
|
);
|
||||||
|
|
||||||
slice::from_raw_parts(data as *const u8, size + 1)
|
let mut size = 0;
|
||||||
})
|
// This will not trigger a 'm' error, because the reference is guaranteed to be of
|
||||||
|
// string type
|
||||||
|
let data = ffi::lua_tolstring(lua.state, -1, &mut size);
|
||||||
|
|
||||||
|
slice::from_raw_parts(data as *const u8, size + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
235
src/table.rs
235
src/table.rs
|
@ -3,7 +3,7 @@ use std::os::raw::c_int;
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use error::Result;
|
use error::Result;
|
||||||
use util::{check_stack, protect_lua, protect_lua_closure, stack_guard};
|
use util::{check_stack, protect_lua, protect_lua_closure, StackGuard};
|
||||||
use types::{Integer, LuaRef, RefType};
|
use types::{Integer, LuaRef, RefType};
|
||||||
use value::{FromLua, ToLua};
|
use value::{FromLua, ToLua};
|
||||||
|
|
||||||
|
@ -52,18 +52,18 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
pub fn set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 6);
|
check_stack(lua.state, 6);
|
||||||
lua.push_ref(&self.0);
|
|
||||||
lua.push_value(key.to_lua(lua)?);
|
|
||||||
lua.push_value(value.to_lua(lua)?);
|
|
||||||
|
|
||||||
unsafe extern "C" fn set_table(state: *mut ffi::lua_State) -> c_int {
|
lua.push_ref(&self.0);
|
||||||
ffi::lua_settable(state, -3);
|
lua.push_value(key.to_lua(lua)?);
|
||||||
1
|
lua.push_value(value.to_lua(lua)?);
|
||||||
}
|
|
||||||
protect_lua(lua.state, 3, set_table)
|
unsafe extern "C" fn set_table(state: *mut ffi::lua_State) -> c_int {
|
||||||
})
|
ffi::lua_settable(state, -3);
|
||||||
|
1
|
||||||
|
}
|
||||||
|
protect_lua(lua.state, 3, set_table)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,19 +98,19 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
|
pub fn get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 5);
|
check_stack(lua.state, 5);
|
||||||
lua.push_ref(&self.0);
|
|
||||||
lua.push_value(key.to_lua(lua)?);
|
|
||||||
|
|
||||||
unsafe extern "C" fn get_table(state: *mut ffi::lua_State) -> c_int {
|
lua.push_ref(&self.0);
|
||||||
ffi::lua_gettable(state, -2);
|
lua.push_value(key.to_lua(lua)?);
|
||||||
1
|
|
||||||
}
|
|
||||||
protect_lua(lua.state, 2, get_table)?;
|
|
||||||
|
|
||||||
V::from_lua(lua.pop_value(), lua)
|
unsafe extern "C" fn get_table(state: *mut ffi::lua_State) -> c_int {
|
||||||
})
|
ffi::lua_gettable(state, -2);
|
||||||
|
1
|
||||||
|
}
|
||||||
|
protect_lua(lua.state, 2, get_table)?;
|
||||||
|
|
||||||
|
V::from_lua(lua.pop_value(), lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,20 +118,20 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn contains_key<K: ToLua<'lua>>(&self, key: K) -> Result<bool> {
|
pub fn contains_key<K: ToLua<'lua>>(&self, key: K) -> Result<bool> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 5);
|
check_stack(lua.state, 5);
|
||||||
lua.push_ref(&self.0);
|
|
||||||
lua.push_value(key.to_lua(lua)?);
|
|
||||||
|
|
||||||
unsafe extern "C" fn get_table(state: *mut ffi::lua_State) -> c_int {
|
lua.push_ref(&self.0);
|
||||||
ffi::lua_gettable(state, -2);
|
lua.push_value(key.to_lua(lua)?);
|
||||||
1
|
|
||||||
}
|
|
||||||
protect_lua(lua.state, 2, get_table)?;
|
|
||||||
|
|
||||||
let has = ffi::lua_isnil(lua.state, -1) == 0;
|
unsafe extern "C" fn get_table(state: *mut ffi::lua_State) -> c_int {
|
||||||
Ok(has)
|
ffi::lua_gettable(state, -2);
|
||||||
})
|
1
|
||||||
|
}
|
||||||
|
protect_lua(lua.state, 2, get_table)?;
|
||||||
|
|
||||||
|
let has = ffi::lua_isnil(lua.state, -1) == 0;
|
||||||
|
Ok(has)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,20 +139,20 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn raw_set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
pub fn raw_set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 6);
|
check_stack(lua.state, 6);
|
||||||
lua.push_ref(&self.0);
|
|
||||||
lua.push_value(key.to_lua(lua)?);
|
|
||||||
lua.push_value(value.to_lua(lua)?);
|
|
||||||
|
|
||||||
unsafe extern "C" fn raw_set(state: *mut ffi::lua_State) -> c_int {
|
lua.push_ref(&self.0);
|
||||||
ffi::lua_rawset(state, -3);
|
lua.push_value(key.to_lua(lua)?);
|
||||||
0
|
lua.push_value(value.to_lua(lua)?);
|
||||||
}
|
|
||||||
protect_lua(lua.state, 3, raw_set)?;
|
|
||||||
|
|
||||||
Ok(())
|
unsafe extern "C" fn raw_set(state: *mut ffi::lua_State) -> c_int {
|
||||||
})
|
ffi::lua_rawset(state, -3);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
protect_lua(lua.state, 3, raw_set)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,14 +160,14 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
|
pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 3);
|
check_stack(lua.state, 3);
|
||||||
lua.push_ref(&self.0);
|
|
||||||
lua.push_value(key.to_lua(lua)?);
|
lua.push_ref(&self.0);
|
||||||
ffi::lua_rawget(lua.state, -2);
|
lua.push_value(key.to_lua(lua)?);
|
||||||
let res = V::from_lua(lua.pop_value(), lua)?;
|
ffi::lua_rawget(lua.state, -2);
|
||||||
Ok(res)
|
let res = V::from_lua(lua.pop_value(), lua)?;
|
||||||
})
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,11 +179,10 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn len(&self) -> Result<Integer> {
|
pub fn len(&self) -> Result<Integer> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 4);
|
check_stack(lua.state, 4);
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
protect_lua_closure(lua.state, 1, 0, |state| ffi::luaL_len(state, -1))
|
protect_lua_closure(lua.state, 1, 0, |state| ffi::luaL_len(state, -1))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,12 +190,11 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn raw_len(&self) -> Integer {
|
pub fn raw_len(&self) -> Integer {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 1);
|
check_stack(lua.state, 1);
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
let len = ffi::lua_rawlen(lua.state, -1);
|
let len = ffi::lua_rawlen(lua.state, -1);
|
||||||
len as Integer
|
len as Integer
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,16 +204,15 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn get_metatable(&self) -> Option<Table<'lua>> {
|
pub fn get_metatable(&self) -> Option<Table<'lua>> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 1);
|
check_stack(lua.state, 1);
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
if ffi::lua_getmetatable(lua.state, -1) == 0 {
|
if ffi::lua_getmetatable(lua.state, -1) == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let table = Table(lua.pop_ref());
|
let table = Table(lua.pop_ref());
|
||||||
Some(table)
|
Some(table)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,16 +223,15 @@ impl<'lua> Table<'lua> {
|
||||||
pub fn set_metatable(&self, metatable: Option<Table<'lua>>) {
|
pub fn set_metatable(&self, metatable: Option<Table<'lua>>) {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, move || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 1);
|
check_stack(lua.state, 1);
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
if let Some(metatable) = metatable {
|
if let Some(metatable) = metatable {
|
||||||
lua.push_ref(&metatable.0);
|
lua.push_ref(&metatable.0);
|
||||||
} else {
|
} else {
|
||||||
ffi::lua_pushnil(lua.state);
|
ffi::lua_pushnil(lua.state);
|
||||||
}
|
}
|
||||||
ffi::lua_setmetatable(lua.state, -2);
|
ffi::lua_setmetatable(lua.state, -2);
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,31 +355,30 @@ where
|
||||||
let lua = self.table.lua;
|
let lua = self.table.lua;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 6);
|
check_stack(lua.state, 6);
|
||||||
|
|
||||||
lua.push_ref(&self.table);
|
lua.push_ref(&self.table);
|
||||||
lua.push_ref(&next_key);
|
lua.push_ref(&next_key);
|
||||||
|
|
||||||
match protect_lua_closure(lua.state, 2, ffi::LUA_MULTRET, |state| {
|
match protect_lua_closure(lua.state, 2, ffi::LUA_MULTRET, |state| {
|
||||||
ffi::lua_next(state, -2) != 0
|
ffi::lua_next(state, -2) != 0
|
||||||
}) {
|
}) {
|
||||||
Ok(false) => None,
|
Ok(false) => None,
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
ffi::lua_pushvalue(lua.state, -2);
|
ffi::lua_pushvalue(lua.state, -2);
|
||||||
let key = lua.pop_value();
|
let key = lua.pop_value();
|
||||||
let value = lua.pop_value();
|
let value = lua.pop_value();
|
||||||
self.next_key = Some(lua.pop_ref());
|
self.next_key = Some(lua.pop_ref());
|
||||||
|
|
||||||
Some((|| {
|
Some((|| {
|
||||||
let key = K::from_lua(key, lua)?;
|
let key = K::from_lua(key, lua)?;
|
||||||
let value = V::from_lua(value, lua)?;
|
let value = V::from_lua(value, lua)?;
|
||||||
Ok((key, value))
|
Ok((key, value))
|
||||||
})())
|
})())
|
||||||
}
|
|
||||||
Err(e) => Some(Err(e)),
|
|
||||||
}
|
}
|
||||||
})
|
Err(e) => Some(Err(e)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -413,22 +408,20 @@ where
|
||||||
let lua = self.table.lua;
|
let lua = self.table.lua;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 5);
|
check_stack(lua.state, 5);
|
||||||
|
|
||||||
lua.push_ref(&self.table);
|
lua.push_ref(&self.table);
|
||||||
match protect_lua_closure(lua.state, 1, 1, |state| {
|
match protect_lua_closure(lua.state, 1, 1, |state| ffi::lua_geti(state, -1, index))
|
||||||
ffi::lua_geti(state, -1, index)
|
{
|
||||||
}) {
|
Ok(ffi::LUA_TNIL) => None,
|
||||||
Ok(ffi::LUA_TNIL) => None,
|
Ok(_) => {
|
||||||
Ok(_) => {
|
let value = lua.pop_value();
|
||||||
let value = lua.pop_value();
|
self.index = Some(index + 1);
|
||||||
self.index = Some(index + 1);
|
Some(V::from_lua(value, lua))
|
||||||
Some(V::from_lua(value, lua))
|
|
||||||
}
|
|
||||||
Err(err) => Some(Err(err)),
|
|
||||||
}
|
}
|
||||||
})
|
Err(err) => Some(Err(err)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::os::raw::c_int;
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use util::{check_stack, check_stack_err, error_traceback, pop_error, stack_guard};
|
use util::{check_stack, check_stack_err, error_traceback, pop_error, StackGuard};
|
||||||
use types::LuaRef;
|
use types::LuaRef;
|
||||||
use value::{FromLuaMulti, MultiValue, ToLuaMulti};
|
use value::{FromLuaMulti, MultiValue, ToLuaMulti};
|
||||||
|
|
||||||
|
@ -78,45 +78,44 @@ impl<'lua> Thread<'lua> {
|
||||||
{
|
{
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 1);
|
check_stack(lua.state, 1);
|
||||||
|
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
let thread_state = ffi::lua_tothread(lua.state, -1);
|
let thread_state = ffi::lua_tothread(lua.state, -1);
|
||||||
|
|
||||||
let status = ffi::lua_status(thread_state);
|
let status = ffi::lua_status(thread_state);
|
||||||
if status != ffi::LUA_YIELD && ffi::lua_gettop(thread_state) == 0 {
|
if status != ffi::LUA_YIELD && ffi::lua_gettop(thread_state) == 0 {
|
||||||
return Err(Error::CoroutineInactive);
|
return Err(Error::CoroutineInactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi::lua_pop(lua.state, 1);
|
ffi::lua_pop(lua.state, 1);
|
||||||
|
|
||||||
let args = args.to_lua_multi(lua)?;
|
let args = args.to_lua_multi(lua)?;
|
||||||
let nargs = args.len() as c_int;
|
let nargs = args.len() as c_int;
|
||||||
check_stack_err(lua.state, nargs)?;
|
check_stack_err(lua.state, nargs)?;
|
||||||
check_stack_err(thread_state, nargs + 1)?;
|
check_stack_err(thread_state, nargs + 1)?;
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
lua.push_value(arg);
|
lua.push_value(arg);
|
||||||
}
|
}
|
||||||
ffi::lua_xmove(lua.state, thread_state, nargs);
|
ffi::lua_xmove(lua.state, thread_state, nargs);
|
||||||
|
|
||||||
let ret = ffi::lua_resume(thread_state, lua.state, nargs);
|
let ret = ffi::lua_resume(thread_state, lua.state, nargs);
|
||||||
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
|
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
|
||||||
error_traceback(thread_state);
|
error_traceback(thread_state);
|
||||||
return Err(pop_error(thread_state, ret));
|
return Err(pop_error(thread_state, ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
let nresults = ffi::lua_gettop(thread_state);
|
let nresults = ffi::lua_gettop(thread_state);
|
||||||
let mut results = MultiValue::new();
|
let mut results = MultiValue::new();
|
||||||
ffi::lua_xmove(thread_state, lua.state, nresults);
|
ffi::lua_xmove(thread_state, lua.state, nresults);
|
||||||
|
|
||||||
check_stack(lua.state, 2);
|
check_stack(lua.state, 2);
|
||||||
for _ in 0..nresults {
|
for _ in 0..nresults {
|
||||||
results.push_front(lua.pop_value());
|
results.push_front(lua.pop_value());
|
||||||
}
|
}
|
||||||
R::from_lua_multi(results, lua)
|
R::from_lua_multi(results, lua)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,22 +123,21 @@ impl<'lua> Thread<'lua> {
|
||||||
pub fn status(&self) -> ThreadStatus {
|
pub fn status(&self) -> ThreadStatus {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 1);
|
check_stack(lua.state, 1);
|
||||||
|
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
let thread_state = ffi::lua_tothread(lua.state, -1);
|
let thread_state = ffi::lua_tothread(lua.state, -1);
|
||||||
ffi::lua_pop(lua.state, 1);
|
ffi::lua_pop(lua.state, 1);
|
||||||
|
|
||||||
let status = ffi::lua_status(thread_state);
|
let status = ffi::lua_status(thread_state);
|
||||||
if status != ffi::LUA_OK && status != ffi::LUA_YIELD {
|
if status != ffi::LUA_OK && status != ffi::LUA_YIELD {
|
||||||
ThreadStatus::Error
|
ThreadStatus::Error
|
||||||
} else if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 {
|
} else if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 {
|
||||||
ThreadStatus::Resumable
|
ThreadStatus::Resumable
|
||||||
} else {
|
} else {
|
||||||
ThreadStatus::Unresumable
|
ThreadStatus::Unresumable
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::string::String as StdString;
|
||||||
|
|
||||||
use ffi;
|
use ffi;
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use util::{check_stack, get_userdata, stack_guard};
|
use util::{check_stack, get_userdata, StackGuard};
|
||||||
use types::{Callback, LuaRef};
|
use types::{Callback, LuaRef};
|
||||||
use value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti};
|
use value::{FromLua, FromLuaMulti, ToLua, ToLuaMulti};
|
||||||
use lua::Lua;
|
use lua::Lua;
|
||||||
|
@ -415,29 +415,28 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
stack_guard(lua.state, move || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 3);
|
check_stack(lua.state, 3);
|
||||||
|
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
|
|
||||||
rlua_assert!(
|
rlua_assert!(
|
||||||
ffi::lua_getmetatable(lua.state, -1) != 0,
|
ffi::lua_getmetatable(lua.state, -1) != 0,
|
||||||
"AnyUserData missing metatable"
|
"AnyUserData missing metatable"
|
||||||
);
|
);
|
||||||
|
|
||||||
ffi::lua_rawgeti(
|
ffi::lua_rawgeti(
|
||||||
lua.state,
|
lua.state,
|
||||||
ffi::LUA_REGISTRYINDEX,
|
ffi::LUA_REGISTRYINDEX,
|
||||||
lua.userdata_metatable::<T>()? as ffi::lua_Integer,
|
lua.userdata_metatable::<T>()? as ffi::lua_Integer,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ffi::lua_rawequal(lua.state, -1, -2) == 0 {
|
if ffi::lua_rawequal(lua.state, -1, -2) == 0 {
|
||||||
Err(Error::UserDataTypeMismatch)
|
Err(Error::UserDataTypeMismatch)
|
||||||
} else {
|
} else {
|
||||||
let res = func(&*get_userdata::<RefCell<T>>(lua.state, -3));
|
let res = func(&*get_userdata::<RefCell<T>>(lua.state, -3));
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,13 +448,12 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
|
pub fn set_user_value<V: ToLua<'lua>>(&self, v: V) -> Result<()> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 2);
|
check_stack(lua.state, 2);
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
lua.push_value(v.to_lua(lua)?);
|
lua.push_value(v.to_lua(lua)?);
|
||||||
ffi::lua_setuservalue(lua.state, -2);
|
ffi::lua_setuservalue(lua.state, -2);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,13 +463,12 @@ impl<'lua> AnyUserData<'lua> {
|
||||||
pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
|
pub fn get_user_value<V: FromLua<'lua>>(&self) -> Result<V> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, || {
|
let _sg = StackGuard::new(lua.state);
|
||||||
check_stack(lua.state, 3);
|
check_stack(lua.state, 3);
|
||||||
lua.push_ref(&self.0);
|
lua.push_ref(&self.0);
|
||||||
ffi::lua_getuservalue(lua.state, -1);
|
ffi::lua_getuservalue(lua.state, -1);
|
||||||
let res = V::from_lua(lua.pop_value(), lua)?;
|
let res = V::from_lua(lua.pop_value(), lua)?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,15 +57,6 @@ impl Drop for StackGuard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run an operation on a lua_State and restores the stack state at the end, using `StackGuard`.
|
|
||||||
pub unsafe fn stack_guard<F, R>(state: *mut ffi::lua_State, op: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce() -> R,
|
|
||||||
{
|
|
||||||
let _stack_guard = StackGuard::new(state);
|
|
||||||
op()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way.
|
// Call a function that calls into the Lua API and may trigger a Lua error (longjmp) in a safe way.
|
||||||
// Wraps the inner function in a call to `lua_pcall`, so the inner function only has access to a
|
// Wraps the inner function in a call to `lua_pcall`, so the inner function only has access to a
|
||||||
// limited lua stack. `nargs` is the same as the the parameter to `lua_pcall`, and `nresults` is
|
// limited lua stack. `nargs` is the same as the the parameter to `lua_pcall`, and `nresults` is
|
||||||
|
|
Loading…
Reference in New Issue