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 {
|
unsafe {
|
||||||
let s = self.state_ptr();
|
let s = self.state_ptr();
|
||||||
lua::lua_rawgeti(s, lua::LUA_REGISTRYINDEX, lua::LUA_RIDX_GLOBALS);
|
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
|
// if the metatable is not made yet, make it
|
||||||
let mt = self.create_userdata_metatable::<T>()?;
|
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)?;
|
mt.push_to_lua_stack(self)?;
|
||||||
} else if ty != lua::LUA_TTABLE {
|
} else if ty != lua::LUA_TTABLE {
|
||||||
return Err(Error::RegistryConflict(name.to_string()));
|
return Err(Error::RegistryConflict(name.to_string()));
|
||||||
|
|
60
src/table.rs
60
src/table.rs
|
@ -5,16 +5,12 @@ use mlua_sys as lua;
|
||||||
|
|
||||||
use crate::{ensure_type, FromLuaStack, LuaRef, PushToLuaStack, Result, StackGuard, State};
|
use crate::{ensure_type, FromLuaStack, LuaRef, PushToLuaStack, Result, StackGuard, State};
|
||||||
|
|
||||||
pub(crate) struct MetaTableInfo {
|
|
||||||
name: Option<String>,
|
|
||||||
lref: LuaRef,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Table<'a> {
|
pub struct Table<'a> {
|
||||||
state: &'a State,
|
state: &'a State,
|
||||||
pub(crate) lref: LuaRef,
|
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> {
|
impl<'a> Table<'a> {
|
||||||
|
@ -31,7 +27,7 @@ impl<'a> Table<'a> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
lref,
|
lref,
|
||||||
meta: None,
|
mt_marker: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,16 +35,10 @@ impl<'a> Table<'a> {
|
||||||
let name_term = format!("{}\0", name);
|
let name_term = format!("{}\0", name);
|
||||||
let name_term_c = name_term.as_str().as_ptr() as *const i8;
|
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);
|
let _g = StackGuard::new(state);
|
||||||
state.ensure_stack(2)?;
|
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();
|
let s = state.state_ptr();
|
||||||
if lua::luaL_newmetatable(s, name_term_c) == 0 {
|
if lua::luaL_newmetatable(s, name_term_c) == 0 {
|
||||||
// lua::luaL_getmetatable does not return the type that was
|
// 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()));
|
return Err(crate::Error::RegistryConflict(name.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua::lua_pushvalue(s, lua::lua_gettop(s));
|
LuaRef::from_stack(state)?
|
||||||
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)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
lref,
|
lref: meta_ref,
|
||||||
meta: Some(meta_ref)
|
mt_marker: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a table with a lua reference to one.
|
/// 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();
|
let s = state.state_ptr();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -91,7 +76,7 @@ impl<'a> Table<'a> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state,
|
state,
|
||||||
lref: lua_ref,
|
lref: lua_ref,
|
||||||
meta: None,
|
mt_marker: is_metatable,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +92,7 @@ impl<'a> Table<'a> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _g = StackGuard::new(self.state);
|
let _g = StackGuard::new(self.state);
|
||||||
|
|
||||||
if let Some(_) = &self.meta {
|
if self.mt_marker {
|
||||||
self.state.ensure_stack(4)?;
|
self.state.ensure_stack(4)?;
|
||||||
} else {
|
} else {
|
||||||
self.state.ensure_stack(3)?;
|
self.state.ensure_stack(3)?;
|
||||||
|
@ -118,11 +103,6 @@ impl<'a> Table<'a> {
|
||||||
val.push_to_lua_stack(self.state)?;
|
val.push_to_lua_stack(self.state)?;
|
||||||
|
|
||||||
lua::lua_settable(s, -3);
|
lua::lua_settable(s, -3);
|
||||||
|
|
||||||
if let Some(mt) = &self.meta {
|
|
||||||
mt.push_to_lua_stack(self.state)?;
|
|
||||||
lua::lua_setmetatable(s, -2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -226,36 +206,26 @@ impl<'a> Table<'a> {
|
||||||
|
|
||||||
/// Set something in the metatable
|
/// Set something in the metatable
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// Does nothing if this table is not a metatable
|
||||||
/// Panics if this table is not a metatable
|
|
||||||
pub fn set_meta<K, V>(&self, key: K, val: V) -> Result<()>
|
pub fn set_meta<K, V>(&self, key: K, val: V) -> Result<()>
|
||||||
where
|
where
|
||||||
K: PushToLuaStack<'a>,
|
K: PushToLuaStack<'a>,
|
||||||
V: PushToLuaStack<'a>
|
V: PushToLuaStack<'a>
|
||||||
{
|
{
|
||||||
let mt = self.meta.as_ref()
|
if self.mt_marker {
|
||||||
.expect("this table is not a meta table!");
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let s = self.state.state_ptr();
|
let s = self.state.state_ptr();
|
||||||
self.state.ensure_stack(3)?;
|
self.state.ensure_stack(3)?;
|
||||||
let _g = StackGuard::new(self.state);
|
let _g = StackGuard::new(self.state);
|
||||||
|
|
||||||
mt.push_to_lua_stack(self.state)?;
|
self.lref.push_to_lua_stack(self.state)?;
|
||||||
key.push_to_lua_stack(self.state)?;
|
key.push_to_lua_stack(self.state)?;
|
||||||
val.push_to_lua_stack(self.state)?;
|
val.push_to_lua_stack(self.state)?;
|
||||||
lua::lua_settable(s, -3);
|
lua::lua_settable(s, -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a handle to the metatable of this table
|
Ok(())
|
||||||
pub fn get_metatable(&self) -> Option<Table> {
|
|
||||||
self.meta.clone()
|
|
||||||
.map(|r|
|
|
||||||
Table::with_ref(self.state, r).unwrap()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +241,6 @@ impl<'a> PushToLuaStack<'a> for Table<'a> {
|
||||||
impl<'a> FromLuaStack<'a> for Table<'a> {
|
impl<'a> FromLuaStack<'a> for Table<'a> {
|
||||||
unsafe fn from_lua_stack(state: &'a State) -> Result<Self> {
|
unsafe fn from_lua_stack(state: &'a State) -> Result<Self> {
|
||||||
ensure_type(state, lua::LUA_TTABLE, -1)?;
|
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