pub mod native_table;
use super::lua_value::LuaValue;
use crate::{LuaResult, TablePtr, lua_vm::LuaError};
use native_table::NativeTable;
const MASK_FLAGS: u32 = (1u32 << 26) - 1;
pub struct LuaTable {
meta: TablePtr,
flags: u32,
pub(crate) impl_table: NativeTable,
}
impl LuaTable {
pub fn new(asize: u32, hsize: u32) -> Self {
Self {
meta: TablePtr::null(),
flags: 0,
impl_table: NativeTable::new(asize, hsize),
}
}
#[inline(always)]
pub(crate) fn invalidate_tm_cache(&mut self) {
self.flags &= !MASK_FLAGS;
}
#[inline(always)]
pub(crate) fn no_tm(&self, tm: u8) -> bool {
self.flags & (1u32 << tm) != 0
}
#[inline(always)]
pub(crate) fn set_tm_absent(&mut self, tm: u8) {
self.flags |= 1u32 << tm;
}
#[inline(always)]
pub(crate) fn meta_ptr(&self) -> TablePtr {
self.meta
}
#[inline(always)]
pub fn has_metatable(&self) -> bool {
!self.meta.is_null()
}
pub fn get_metatable(&self) -> Option<LuaValue> {
if self.meta.is_null() {
None
} else {
Some(LuaValue::table(self.meta))
}
}
pub(crate) fn set_metatable(&mut self, metatable: Option<LuaValue>) {
if let Some(meta) = metatable {
if let Some(table_ptr) = meta.as_table_ptr() {
self.meta = table_ptr;
} else {
self.meta = TablePtr::null();
}
} else {
self.meta = TablePtr::null();
}
}
pub fn len(&self) -> usize {
self.impl_table.len()
}
pub fn hash_size(&self) -> usize {
self.impl_table.hash_size()
}
#[inline]
pub fn compute_mem_size(&self) -> usize {
self.impl_table.compute_mem_size()
}
pub fn is_array(&self) -> bool {
self.impl_table.hash_size() == 0
}
#[inline(always)]
pub fn raw_geti(&self, key: i64) -> Option<LuaValue> {
self.impl_table.get_int(key)
}
#[inline(always)]
pub(crate) fn raw_seti(&mut self, key: i64, value: LuaValue) -> isize {
self.impl_table.set_int(key, value)
}
#[inline(always)]
pub fn raw_get(&self, key: &LuaValue) -> Option<LuaValue> {
self.impl_table.raw_get(key)
}
#[inline(always)]
pub(crate) fn raw_set(&mut self, key: &LuaValue, value: LuaValue) -> (bool, isize) {
let (new_key, delta) = self.impl_table.raw_set(key, value);
if new_key {
self.invalidate_tm_cache();
}
(new_key, delta)
}
#[inline]
pub fn next(&self, input_key: &LuaValue) -> Result<Option<(LuaValue, LuaValue)>, ()> {
self.impl_table.next(input_key)
}
pub fn remove_array_at(&mut self, i: i64) -> LuaResult<LuaValue> {
self.impl_table
.remove_at(i)
.ok_or(LuaError::IndexOutOfBounds)
}
pub fn iter_all(&self) -> Vec<(LuaValue, LuaValue)> {
let mut result = Vec::new();
self.impl_table.for_each_entry(|k, v| {
result.push((k, v));
});
result
}
pub fn iter_keys(&self) -> Vec<LuaValue> {
let mut result = Vec::new();
self.impl_table.for_each_entry(|k, _v| {
result.push(k);
});
result
}
pub(crate) fn for_each_entry<F>(&self, f: F)
where
F: FnMut(LuaValue, LuaValue),
{
self.impl_table.for_each_entry(f);
}
}