From 6a0393f3467ecec921fbfdcf150b7569c3b0ae5b Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Tue, 23 Jan 2024 20:28:19 -0500 Subject: [PATCH] Add Table::raw* --- src/main.rs | 8 ++++- src/table.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 903c748..a6f8fc1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,6 +79,10 @@ fn main() -> Result<()> { assert_eq!(num, 50); println!("Did math in lua and got 50!"); + unsafe { + assert_eq!(lua::lua_gettop(lua.state_ptr()), 0); // ensure that nothing is left on the stack + } + Ok(()) } @@ -171,7 +175,9 @@ impl<'a> FromLuaStack<'a> for i32 { let s = state.state_ptr(); if lua::lua_isnumber(s, -1) == 1 { - Ok(lua::lua_tonumber(s, -1) as i32) + let v = lua::lua_tonumber(s, -1) as i32; + lua::lua_pop(s, -1); + Ok(v) } else { let lua_ty = lua_type(s, -1); let typec = CStr::from_ptr(lua_typename(s, lua_ty)); diff --git a/src/table.rs b/src/table.rs index f12d33d..eb8fb2d 100644 --- a/src/table.rs +++ b/src/table.rs @@ -10,6 +10,7 @@ pub struct Table<'a> { } impl<'a> Table<'a> { + /// Create a new table pub fn new(state: &'a State) -> Result { let lref = unsafe { state.ensure_stack(1)?; @@ -25,6 +26,7 @@ impl<'a> Table<'a> { }) } + /// Construct a table with a lua reference to one. pub fn with_ref(state: &'a State, lua_ref: LuaRef) -> Result { let s = state.state_ptr(); @@ -42,6 +44,9 @@ impl<'a> Table<'a> { }) } + /// Set a key to a value in the table. + /// + /// This may trigger the `__newindex` metamethod, see [`Table::raw_set`] pub fn set(&self, key: K, val: V) -> Result<()> where K: PushToLuaStack, @@ -62,6 +67,9 @@ impl<'a> Table<'a> { Ok(()) } + /// Get a value from the table. + /// + /// This may trigger the `__index` metamethod, see [`Table::raw_get`] pub fn get(&'a self, key: K) -> Result where K: PushToLuaStack, @@ -72,10 +80,80 @@ impl<'a> Table<'a> { self.lref.push_to_lua_stack(self.state)?; key.push_to_lua_stack(self.state)?; lua::lua_gettable(s, -2); // table[key] is at top of stack - V::from_lua_stack(self.state) + + let top = lua::lua_gettop(s); + let val = V::from_lua_stack(self.state)?; + let new_top = lua::lua_gettop(s); + debug_assert!(new_top < top, "V::from_lua_stack did not remove anything from the stack!"); + + Ok(val) + } + } + + /// Returns the length of the table. + /// + /// This may trigger the `__len` metamethod, see [`Table::raw_len`] + pub fn len(&self) -> Result { + let s = self.state.state_ptr(); + unsafe { + self.lref.push_to_lua_stack(self.state)?; + lua::lua_len(s, -1); + + let len = lua::lua_tonumber(s, -1); + lua::lua_pop(self.state.state_ptr(), -1); + + Ok(len as u64) + } + } + + /// Set a key to a value in the table without calling any meta methods. + pub fn raw_set(&self, key: K, val: V) -> Result<()> + where + K: PushToLuaStack, + V: PushToLuaStack + { + let s = self.state.state_ptr(); + unsafe { + self.state.ensure_stack(3)?; + + self.lref.push_to_lua_stack(self.state)?; + key.push_to_lua_stack(self.state)?; + val.push_to_lua_stack(self.state)?; + + lua::lua_rawset(s, -3); + lua::lua_pop(self.state.state_ptr(), -1); } - //todo!() + Ok(()) + } + + /// Get a value from the table without calling any meta methods. + pub fn raw_get(&'a self, key: K) -> Result + where + K: PushToLuaStack, + V: FromLuaStack<'a>, + { + let s = self.state.state_ptr(); + unsafe { + self.lref.push_to_lua_stack(self.state)?; + key.push_to_lua_stack(self.state)?; + lua::lua_rawget(s, -2); // table[key] is at top of stack + V::from_lua_stack(self.state) + } + } + + /// Get the length of the table without calling any meta methods. + pub fn raw_len(&self) -> Result { + let s = self.state.state_ptr(); + unsafe { + self.lref.push_to_lua_stack(self.state)?; + lua::lua_rawlen(s, -1); + + let len = lua::lua_tonumber(s, -1); + lua::lua_pop(self.state.state_ptr(), -1); + + Ok(len as u64) + } } }