summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/ffi.rs1
-rw-r--r--src/lua.rs80
-rw-r--r--src/tests.rs9
-rw-r--r--src/util.rs11
5 files changed, 60 insertions, 43 deletions
diff --git a/Cargo.toml b/Cargo.toml
index d4ebe85..94d65f6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rlua"
-version = "0.4.3"
+version = "0.4.4"
authors = ["kyren <catherine@chucklefish.org>"]
description = "High level bindings to Lua 5.3"
repository = "https://github.com/chucklefish/rlua"
diff --git a/src/ffi.rs b/src/ffi.rs
index 1d210e9..1bf3b17 100644
--- a/src/ffi.rs
+++ b/src/ffi.rs
@@ -106,6 +106,7 @@ extern "C" {
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_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_rawequal(state: *mut lua_State, index1: c_int, index2: c_int) -> c_int;
diff --git a/src/lua.rs b/src/lua.rs
index cf668a8..a1aeda5 100644
--- a/src/lua.rs
+++ b/src/lua.rs
@@ -152,21 +152,38 @@ pub struct LuaTable<'lua>(LuaRef<'lua>);
impl<'lua> LuaTable<'lua> {
pub fn set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> LuaResult<()> {
let lua = self.0.lua;
+ let key = key.to_lua(lua)?;
+ let value = value.to_lua(lua)?;
unsafe {
- stack_guard(lua.state, 0, || {
- check_stack(lua.state, 3)?;
- lua.push_ref(lua.state, &self.0);
- lua.push_value(lua.state, key.to_lua(lua)?)?;
- lua.push_value(lua.state, value.to_lua(lua)?)?;
- error_guard(lua.state, 3, 0, |state| {
- ffi::lua_settable(state, -3);
- Ok(())
- })?;
+ error_guard(lua.state, 0, 0, |state| {
+ check_stack(state, 3)?;
+ lua.push_ref(state, &self.0);
+ lua.push_value(state, key)?;
+ lua.push_value(state, value)?;
+ ffi::lua_settable(state, -3);
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<()> {
let lua = self.0.lua;
unsafe {
@@ -182,17 +199,15 @@ 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
+ pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> LuaResult<V> {
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(())
- })?;
+ ffi::lua_gettable(lua.state, -2);
let res = V::from_lua(lua.pop_value(lua.state)?, lua)?;
ffi::lua_pop(lua.state, 1);
Ok(res)
@@ -200,29 +215,29 @@ impl<'lua> LuaTable<'lua> {
}
}
- pub fn raw_get<K: ToLua<'lua>, V: FromLua<'lua>>(&self, key: K) -> LuaResult<V> {
+ /// Equivalent to the result of the lua '#' operator.
+ pub fn length(&self) -> LuaResult<LuaInteger> {
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)?)?;
- ffi::lua_gettable(lua.state, -2);
- let res = V::from_lua(lua.pop_value(lua.state)?, lua)?;
- ffi::lua_pop(lua.state, 1);
- Ok(res)
+ 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.
- pub fn length(&self) -> LuaResult<LuaInteger> {
+ /// 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;
unsafe {
stack_guard(lua.state, 0, || {
check_stack(lua.state, 1)?;
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)?;
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);
while ffi::lua_next(lua.state, -2) != 0 {
@@ -1271,14 +1286,3 @@ impl Lua {
static LUA_USERDATA_REGISTRY_KEY: u8 = 0;
static FUNCTION_METATABLE_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(())
- }
-}
diff --git a/src/tests.rs b/src/tests.rs
index 1832616..5a499ef 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -558,9 +558,10 @@ fn test_table_error() {
.unwrap();
let bad_table: LuaTable = lua.get("table").unwrap();
- assert!(bad_table.set("key", 1).is_err());
- assert!(bad_table.get::<_, i32>("key").is_err());
+ assert!(bad_table.set(1, 1).is_err());
+ assert!(bad_table.get::<_, i32>(1).is_err());
assert!(bad_table.length().is_err());
- assert!(bad_table.raw_set("key", 1).is_ok());
- assert!(bad_table.raw_get::<_, i32>("key").is_ok());
+ assert!(bad_table.raw_set(1, 1).is_ok());
+ assert!(bad_table.raw_get::<_, i32>(1).is_ok());
+ assert_eq!(bad_table.raw_length().unwrap(), 1);
}
diff --git a/src/util.rs b/src/util.rs
index 2ba263c..c6c5576 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -102,6 +102,17 @@ pub unsafe fn error_guard<F, R>(state: *mut ffi::lua_State,
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) {
ffi::lua_pushlstring(state, s.as_ptr() as *const c_char, s.len());
}