diff --git a/src/table.rs b/src/table.rs index 17a25b4..6faaae7 100644 --- a/src/table.rs +++ b/src/table.rs @@ -45,7 +45,6 @@ impl OwnedTable { } } -#[allow(clippy::len_without_is_empty)] impl<'lua> Table<'lua> { /// Sets a key-value pair in the table. /// @@ -150,11 +149,15 @@ impl<'lua> Table<'lua> { } /// Checks whether the table contains a non-nil value for `key`. + /// + /// This might invoke the `__index` metamethod. pub fn contains_key>(&self, key: K) -> Result { Ok(self.get::<_, Value>(key)? != Value::Nil) } /// Appends a value to the back of the table. + /// + /// This might invoke the `__len` and `__newindex` metamethods. pub fn push>(&self, value: V) -> Result<()> { // Fast track if !self.has_metatable() { @@ -179,6 +182,8 @@ impl<'lua> Table<'lua> { } /// Removes the last element from the table and returns it. + /// + /// This might invoke the `__len` and `__newindex` metamethods. pub fn pop>(&self) -> Result { // Fast track if !self.has_metatable() { @@ -492,6 +497,32 @@ impl<'lua> Table<'lua> { unsafe { ffi::lua_rawlen(ref_thread, self.0.index) as Integer } } + /// Returns `true` if the table is empty, without invoking metamethods. + /// + /// It checks both the array part and the hash part. + pub fn is_empty(&self) -> bool { + // Check array part + if self.raw_len() != 0 { + return false; + } + + // Check hash part + let lua = self.0.lua; + let state = lua.state(); + unsafe { + let _sg = StackGuard::new(state); + assert_stack(state, 4); + + lua.push_ref(&self.0); + ffi::lua_pushnil(state); + if ffi::lua_next(state, -2) != 0 { + return false; + } + } + + true + } + /// Returns a reference to the metatable of this table, or `None` if no metatable is set. /// /// Unlike the `getmetatable` Lua function, this method ignores the `__metatable` field. @@ -717,10 +748,11 @@ impl<'lua> Table<'lua> { lua.push_ref(&self.0); lua.push_value(value)?; + let idx = idx.try_into().unwrap(); if lua.unlikely_memory_error() { - ffi::lua_rawseti(state, -2, idx as _); + ffi::lua_rawseti(state, -2, idx); } else { - protect_lua!(state, 2, 0, |state| ffi::lua_rawseti(state, -2, idx as _))?; + protect_lua!(state, 2, 0, |state| ffi::lua_rawseti(state, -2, idx))?; } Ok(()) } diff --git a/tests/table.rs b/tests/table.rs index 1d89562..e89e258 100644 --- a/tests/table.rs +++ b/tests/table.rs @@ -1,7 +1,7 @@ use mlua::{Error, Lua, Nil, Result, Table, TableExt, Value}; #[test] -fn test_set_get() -> Result<()> { +fn test_globals_set_get() -> Result<()> { let lua = Lua::new(); let globals = lua.globals(); @@ -43,6 +43,7 @@ fn test_table() -> Result<()> { let table3 = globals.get::<_, Table>("table3")?; assert_eq!(table1.len()?, 5); + assert!(!table1.is_empty()); assert_eq!( table1 .clone() @@ -60,6 +61,7 @@ fn test_table() -> Result<()> { assert_eq!(table1, [1, 2, 3, 4, 5]); assert_eq!(table2.len()?, 0); + assert!(table2.is_empty()); assert_eq!( table2 .clone() @@ -192,8 +194,10 @@ fn test_table_clear() -> Result<()> { ) .eval::()?; assert_eq!(t2.raw_len(), 3); + assert!(!t2.is_empty()); t2.clear()?; assert_eq!(t2.raw_len(), 0); + assert!(t2.is_empty()); assert_eq!(t2.raw_get::<_, Value>("a")?, Value::Nil); assert_ne!(t2.get_metatable(), None);