use crate::runtime::heap::Gc;
use crate::runtime::value::Value;
use crate::runtime::Table;
use crate::vm::error::LuaError;
use crate::vm::exec::Vm;
use crate::vm::into_value::IntoValue;
pub struct TableBuilder<'vm> {
vm: &'vm mut Vm,
t: Gc<Table>,
}
impl<'vm> TableBuilder<'vm> {
pub fn with<K, V>(self, k: K, v: V) -> Self
where
K: IntoValue,
V: IntoValue,
{
let TableBuilder { vm, t } = self;
let k = k.into_value(vm);
let v = v.into_value(vm);
unsafe { t.as_mut() }
.set(&mut vm.heap, k, v)
.expect("table builder overflow");
TableBuilder { vm, t }
}
pub fn try_with<K, V>(self, k: K, v: V) -> Result<Self, LuaError>
where
K: IntoValue,
V: IntoValue,
{
let TableBuilder { vm, t } = self;
let k = k.into_value(vm);
let v = v.into_value(vm);
unsafe { t.as_mut() }.set(&mut vm.heap, k, v)?;
Ok(TableBuilder { vm, t })
}
pub fn build(self) -> Gc<Table> {
let TableBuilder { vm, t } = self;
vm.heap
.barrier_back(t.as_ptr() as *mut crate::runtime::heap::GcHeader);
t
}
}
impl Vm {
pub fn new_table(&mut self) -> TableBuilder<'_> {
let t = self.heap.new_table();
TableBuilder { vm: self, t }
}
pub fn table_of<K, V, const N: usize>(&mut self, entries: [(K, V); N]) -> Gc<Table>
where
K: IntoValue,
V: IntoValue,
{
let mut b = self.new_table();
for (k, v) in entries {
b = b.with(k, v);
}
b.build()
}
}