make it so a Table can only be a normal table, or a metatable, not both at the same time
This commit is contained in:
parent
2b03b55014
commit
9ef4203619
|
@ -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::<T>()?;
|
||||
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()));
|
||||
|
|
74
src/table.rs
74
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<String>,
|
||||
lref: LuaRef,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Table<'a> {
|
||||
state: &'a State,
|
||||
pub(crate) lref: LuaRef,
|
||||
pub(crate) meta: Option<LuaRef>, // 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<Self> {
|
||||
pub fn with_ref(state: &'a State, lua_ref: LuaRef, is_metatable: bool) -> Result<Self> {
|
||||
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<K, V>(&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<Table> {
|
||||
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<Self> {
|
||||
ensure_type(state, lua::LUA_TTABLE, -1)?;
|
||||
Table::with_ref(state, LuaRef::from_stack(state)?)
|
||||
Table::with_ref(state, LuaRef::from_stack(state)?, false)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue