Somewhat smarter strategy for error_guard calls, less ungodly slow.
Also add raw_length table function
This commit is contained in:
parent
e4052bb4d4
commit
b3218137e1
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rlua"
|
name = "rlua"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
authors = ["kyren <catherine@chucklefish.org>"]
|
authors = ["kyren <catherine@chucklefish.org>"]
|
||||||
description = "High level bindings to Lua 5.3"
|
description = "High level bindings to Lua 5.3"
|
||||||
repository = "https://github.com/chucklefish/rlua"
|
repository = "https://github.com/chucklefish/rlua"
|
||||||
|
|
|
@ -106,6 +106,7 @@ extern "C" {
|
||||||
pub fn lua_setmetatable(state: *mut lua_State, index: c_int);
|
pub fn lua_setmetatable(state: *mut lua_State, index: c_int);
|
||||||
|
|
||||||
pub fn lua_len(state: *mut lua_State, index: c_int);
|
pub fn lua_len(state: *mut lua_State, index: c_int);
|
||||||
|
pub fn lua_rawlen(state: *mut lua_State, index: c_int) -> usize;
|
||||||
pub fn lua_next(state: *mut lua_State, index: c_int) -> c_int;
|
pub fn lua_next(state: *mut lua_State, index: c_int) -> c_int;
|
||||||
pub fn lua_rawequal(state: *mut lua_State, index1: c_int, index2: c_int) -> c_int;
|
pub fn lua_rawequal(state: *mut lua_State, index1: c_int, index2: c_int) -> c_int;
|
||||||
|
|
||||||
|
|
84
src/lua.rs
84
src/lua.rs
|
@ -152,21 +152,38 @@ pub struct LuaTable<'lua>(LuaRef<'lua>);
|
||||||
impl<'lua> LuaTable<'lua> {
|
impl<'lua> LuaTable<'lua> {
|
||||||
pub fn set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> LuaResult<()> {
|
pub fn set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> LuaResult<()> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
|
let key = key.to_lua(lua)?;
|
||||||
|
let value = value.to_lua(lua)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, 0, || {
|
error_guard(lua.state, 0, 0, |state| {
|
||||||
check_stack(lua.state, 3)?;
|
check_stack(state, 3)?;
|
||||||
lua.push_ref(lua.state, &self.0);
|
lua.push_ref(state, &self.0);
|
||||||
lua.push_value(lua.state, key.to_lua(lua)?)?;
|
lua.push_value(state, key)?;
|
||||||
lua.push_value(lua.state, value.to_lua(lua)?)?;
|
lua.push_value(state, value)?;
|
||||||
error_guard(lua.state, 3, 0, |state| {
|
ffi::lua_settable(state, -3);
|
||||||
ffi::lua_settable(state, -3);
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> LuaResult<V> {
|
||||||
|
let lua = self.0.lua;
|
||||||
|
let key = key.to_lua(lua)?;
|
||||||
|
unsafe {
|
||||||
|
let res = error_guard(lua.state, 0, 0, |state| {
|
||||||
|
check_stack(state, 2)?;
|
||||||
|
lua.push_ref(state, &self.0);
|
||||||
|
lua.push_value(state, key.to_lua(lua)?)?;
|
||||||
|
ffi::lua_gettable(state, -2);
|
||||||
|
let res = lua.pop_value(state)?;
|
||||||
|
ffi::lua_pop(state, 1);
|
||||||
|
Ok(res)
|
||||||
|
})?;
|
||||||
|
V::from_lua(res, lua)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a field in the table, without invoking metamethods
|
||||||
pub fn raw_set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> LuaResult<()> {
|
pub fn raw_set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> LuaResult<()> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -182,24 +199,7 @@ impl<'lua> LuaTable<'lua> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> LuaResult<V> {
|
/// Get a field in the table, without invoking metamethods
|
||||||
let lua = self.0.lua;
|
|
||||||
unsafe {
|
|
||||||
stack_guard(lua.state, 0, || {
|
|
||||||
check_stack(lua.state, 2)?;
|
|
||||||
lua.push_ref(lua.state, &self.0);
|
|
||||||
lua.push_value(lua.state, key.to_lua(lua)?)?;
|
|
||||||
error_guard(lua.state, 2, 2, |state| {
|
|
||||||
ffi::lua_gettable(state, -2);
|
|
||||||
Ok(())
|
|
||||||
})?;
|
|
||||||
let res = V::from_lua(lua.pop_value(lua.state)?, lua)?;
|
|
||||||
ffi::lua_pop(lua.state, 1);
|
|
||||||
Ok(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> LuaResult<V> {
|
pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> LuaResult<V> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -217,12 +217,27 @@ impl<'lua> LuaTable<'lua> {
|
||||||
|
|
||||||
/// Equivalent to the result of the lua '#' operator.
|
/// Equivalent to the result of the lua '#' operator.
|
||||||
pub fn length(&self) -> LuaResult<LuaInteger> {
|
pub fn length(&self) -> LuaResult<LuaInteger> {
|
||||||
|
let lua = self.0.lua;
|
||||||
|
unsafe {
|
||||||
|
error_guard(lua.state, 0, 0, |state| {
|
||||||
|
check_stack(state, 1)?;
|
||||||
|
lua.push_ref(state, &self.0);
|
||||||
|
Ok(ffi::luaL_len(state, -1))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Equivalent to the result of the lua '#' operator, without invoking the
|
||||||
|
/// __len metamethod.
|
||||||
|
pub fn raw_length(&self) -> LuaResult<LuaInteger> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
unsafe {
|
unsafe {
|
||||||
stack_guard(lua.state, 0, || {
|
stack_guard(lua.state, 0, || {
|
||||||
check_stack(lua.state, 1)?;
|
check_stack(lua.state, 1)?;
|
||||||
lua.push_ref(lua.state, &self.0);
|
lua.push_ref(lua.state, &self.0);
|
||||||
error_guard(lua.state, 1, 0, |state| Ok(ffi::luaL_len(state, -1)))
|
let len = ffi::lua_rawlen(lua.state, -1);
|
||||||
|
ffi::lua_pop(lua.state, 1);
|
||||||
|
Ok(len as LuaInteger)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +279,7 @@ impl<'lua> LuaTable<'lua> {
|
||||||
check_stack(lua.state, 4)?;
|
check_stack(lua.state, 4)?;
|
||||||
lua.push_ref(lua.state, &self.0);
|
lua.push_ref(lua.state, &self.0);
|
||||||
|
|
||||||
let len = error_guard(lua.state, 1, 1, |state| Ok(ffi::luaL_len(state, -1)))?;
|
let len = ffi::lua_rawlen(lua.state, -1) as ffi::lua_Integer;
|
||||||
ffi::lua_pushnil(lua.state);
|
ffi::lua_pushnil(lua.state);
|
||||||
|
|
||||||
while ffi::lua_next(lua.state, -2) != 0 {
|
while ffi::lua_next(lua.state, -2) != 0 {
|
||||||
|
@ -1271,14 +1286,3 @@ impl Lua {
|
||||||
static LUA_USERDATA_REGISTRY_KEY: u8 = 0;
|
static LUA_USERDATA_REGISTRY_KEY: u8 = 0;
|
||||||
static FUNCTION_METATABLE_REGISTRY_KEY: u8 = 0;
|
static FUNCTION_METATABLE_REGISTRY_KEY: u8 = 0;
|
||||||
static TOP_STATE_REGISTRY_KEY: u8 = 0;
|
static TOP_STATE_REGISTRY_KEY: u8 = 0;
|
||||||
|
|
||||||
// If the return code indicates an error, pops the error off of the stack and
|
|
||||||
// returns Err. If the error was actually a rust panic, clears the current lua
|
|
||||||
// stack and panics.
|
|
||||||
unsafe fn handle_error(state: *mut ffi::lua_State, ret: c_int) -> LuaResult<()> {
|
|
||||||
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
|
|
||||||
Err(pop_error(state))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -558,9 +558,10 @@ fn test_table_error() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let bad_table: LuaTable = lua.get("table").unwrap();
|
let bad_table: LuaTable = lua.get("table").unwrap();
|
||||||
assert!(bad_table.set("key", 1).is_err());
|
assert!(bad_table.set(1, 1).is_err());
|
||||||
assert!(bad_table.get::<_, i32>("key").is_err());
|
assert!(bad_table.get::<_, i32>(1).is_err());
|
||||||
assert!(bad_table.length().is_err());
|
assert!(bad_table.length().is_err());
|
||||||
assert!(bad_table.raw_set("key", 1).is_ok());
|
assert!(bad_table.raw_set(1, 1).is_ok());
|
||||||
assert!(bad_table.raw_get::<_, i32>("key").is_ok());
|
assert!(bad_table.raw_get::<_, i32>(1).is_ok());
|
||||||
|
assert_eq!(bad_table.raw_length().unwrap(), 1);
|
||||||
}
|
}
|
||||||
|
|
11
src/util.rs
11
src/util.rs
|
@ -102,6 +102,17 @@ pub unsafe fn error_guard<F, R>(state: *mut ffi::lua_State,
|
||||||
Ok(res.unwrap())
|
Ok(res.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the return code indicates an error, pops the error off of the stack and
|
||||||
|
// returns Err. If the error was actually a rust panic, clears the current lua
|
||||||
|
// stack and panics.
|
||||||
|
pub unsafe fn handle_error(state: *mut ffi::lua_State, ret: c_int) -> LuaResult<()> {
|
||||||
|
if ret != ffi::LUA_OK && ret != ffi::LUA_YIELD {
|
||||||
|
Err(pop_error(state))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn push_string(state: *mut ffi::lua_State, s: &str) {
|
pub unsafe fn push_string(state: *mut ffi::lua_State, s: &str) {
|
||||||
ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len());
|
ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue