From 9ef42036195806ee7bdc42e5c202e75e5551c02b Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Sat, 27 Jan 2024 11:00:02 -0500 Subject: [PATCH] make it so a Table can only be a normal table, or a metatable, not both at the same time --- src/state.rs | 4 +-- src/table.rs | 74 ++++++++++++++++------------------------------------ 2 files changed, 24 insertions(+), 54 deletions(-) diff --git a/src/state.rs b/src/state.rs index 918dd59..d82a50b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -173,7 +173,7 @@ impl State { unsafe { let s = self.state_ptr(); lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, lua::LUA_RIDX_GLOBALS); - Table::with_ref(self, LuaRef::from_stack(self)?) + Table::with_ref(self, LuaRef::from_stack(self)?, false) } } @@ -297,7 +297,7 @@ impl State { // if the metatable is not made yet, make it let mt = self.create_userdata_metatable::()?; - let mt = mt.get_metatable().unwrap(); // the table 100% has a metatable + //let mt = mt.get_metatable().unwrap(); // the table 100% has a metatable mt.push_to_lua_stack(self)?; } else if ty != lua::LUA_TTABLE { return Err(Error::RegistryConflict(name.to_string())); diff --git a/src/table.rs b/src/table.rs index 3c1530f..d27960d 100644 --- a/src/table.rs +++ b/src/table.rs @@ -5,16 +5,12 @@ use mlua_sys as lua; use crate::{ensure_type, FromLuaStack, LuaRef, PushToLuaStack, Result, StackGuard, State}; -pub(crate) struct MetaTableInfo { - name: Option, - lref: LuaRef, -} - #[derive(Clone)] pub struct Table<'a> { state: &'a State, pub(crate) lref: LuaRef, - pub(crate) meta: Option, // Some if this table is a metatable + /// a boolean indicating if this Table is a Metatable + mt_marker: bool, } impl<'a> Table<'a> { @@ -31,7 +27,7 @@ impl<'a> Table<'a> { Ok(Self { state, lref, - meta: None, + mt_marker: false, }) } @@ -39,16 +35,10 @@ impl<'a> Table<'a> { let name_term = format!("{}\0", name); let name_term_c = name_term.as_str().as_ptr() as *const i8; - let (lref, meta_ref) = unsafe { + let meta_ref = unsafe { let _g = StackGuard::new(state); state.ensure_stack(2)?; - // create the table, this will be retrieved from - // stack after the metatable is created - let s = state.state_ptr(); - lua::lua_newtable(s); - //let table_idx = lua::lua_gettop(s); - let s = state.state_ptr(); if lua::luaL_newmetatable(s, name_term_c) == 0 { // lua::luaL_getmetatable does not return the type that was @@ -60,23 +50,18 @@ impl<'a> Table<'a> { return Err(crate::Error::RegistryConflict(name.to_string())); } } - lua::lua_pushvalue(s, lua::lua_gettop(s)); - lua::lua_setmetatable(s, -3); // -3 here since the metatable was added twice - let meta = LuaRef::from_stack(state)?; - - // retrieve the table created before the metatable - (LuaRef::from_stack(state)?, meta) + LuaRef::from_stack(state)? }; Ok(Self { state, - lref, - meta: Some(meta_ref) + lref: meta_ref, + mt_marker: true }) } /// Construct a table with a lua reference to one. - pub fn with_ref(state: &'a State, lua_ref: LuaRef) -> Result { + pub fn with_ref(state: &'a State, lua_ref: LuaRef, is_metatable: bool) -> Result { let s = state.state_ptr(); unsafe { @@ -91,7 +76,7 @@ impl<'a> Table<'a> { Ok(Self { state, lref: lua_ref, - meta: None, + mt_marker: is_metatable, }) } @@ -107,7 +92,7 @@ impl<'a> Table<'a> { unsafe { let _g = StackGuard::new(self.state); - if let Some(_) = &self.meta { + if self.mt_marker { self.state.ensure_stack(4)?; } else { self.state.ensure_stack(3)?; @@ -118,11 +103,6 @@ impl<'a> Table<'a> { val.push_to_lua_stack(self.state)?; lua::lua_settable(s, -3); - - if let Some(mt) = &self.meta { - mt.push_to_lua_stack(self.state)?; - lua::lua_setmetatable(s, -2); - } } Ok(()) @@ -226,37 +206,27 @@ impl<'a> Table<'a> { /// Set something in the metatable /// - /// # Panics - /// Panics if this table is not a metatable + /// Does nothing if this table is not a metatable pub fn set_meta(&self, key: K, val: V) -> Result<()> where K: PushToLuaStack<'a>, V: PushToLuaStack<'a> { - let mt = self.meta.as_ref() - .expect("this table is not a meta table!"); + if self.mt_marker { + unsafe { + let s = self.state.state_ptr(); + self.state.ensure_stack(3)?; + let _g = StackGuard::new(self.state); - unsafe { - let s = self.state.state_ptr(); - self.state.ensure_stack(3)?; - let _g = StackGuard::new(self.state); - - mt.push_to_lua_stack(self.state)?; - key.push_to_lua_stack(self.state)?; - val.push_to_lua_stack(self.state)?; - lua::lua_settable(s, -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_settable(s, -3); + } } Ok(()) } - - /// Returns a handle to the metatable of this table - pub fn get_metatable(&self) -> Option { - self.meta.clone() - .map(|r| - Table::with_ref(self.state, r).unwrap() - ) - } } impl<'a> PushToLuaStack<'a> for Table<'a> { @@ -271,6 +241,6 @@ impl<'a> PushToLuaStack<'a> for Table<'a> { impl<'a> FromLuaStack<'a> for Table<'a> { unsafe fn from_lua_stack(state: &'a State) -> Result { ensure_type(state, lua::LUA_TTABLE, -1)?; - Table::with_ref(state, LuaRef::from_stack(state)?) + Table::with_ref(state, LuaRef::from_stack(state)?, false) } } \ No newline at end of file