use crate::functions::write_byte::write_byte;
use crate::functions::write_var_int::write_var_int;
use crate::records::bytecode_builder::BytecodeBuilder;
use crate::records::string_ref::StringRef;
use luaur_common::enums::luau_bytecode_tag::{
LBC_TYPE_VERSION_MAX, LBC_TYPE_VERSION_MIN, LBC_VERSION_MAX, LBC_VERSION_MIN,
};
use luaur_common::macros::luau_assert::LUAU_ASSERT;
impl BytecodeBuilder {
pub fn finalize(&mut self) {
LUAU_ASSERT!(self.bytecode.is_empty());
for i in 0..self.userdata_types.len() {
if self.userdata_types[i].used {
let sref = {
let name = &self.userdata_types[i].name;
StringRef {
data: name.as_ptr() as *const i8,
length: name.len(),
}
};
self.userdata_types[i].nameRef = self.add_string_table_entry(sref);
}
}
let mut capacity: usize = 16;
for (string_ref, _index) in self.string_table.iter() {
capacity += string_ref.length + 2;
}
for func in &self.functions {
capacity += func.data.len();
}
let mut bytecode = core::mem::take(&mut self.bytecode);
bytecode.reserve(capacity);
let version = self.get_version();
LUAU_ASSERT!(version >= LBC_VERSION_MIN.0 as u8 && version <= LBC_VERSION_MAX.0 as u8);
unsafe {
bytecode.as_mut_vec().push(version);
}
let typesversion = self.get_type_encoding_version();
LUAU_ASSERT!(
typesversion >= LBC_TYPE_VERSION_MIN.0 as u8
&& typesversion <= LBC_TYPE_VERSION_MAX.0 as u8
);
write_byte(&mut bytecode, typesversion);
self.write_string_table(&mut bytecode);
for i in 0..self.userdata_types.len() {
if self.userdata_types[i].used {
write_byte(&mut bytecode, (i + 1) as u8);
write_var_int(&mut bytecode, self.userdata_types[i].nameRef as u64);
}
}
write_byte(&mut bytecode, 0);
write_var_int(&mut bytecode, self.functions.len() as u64);
for func in &self.functions {
unsafe {
bytecode
.as_mut_vec()
.extend_from_slice(func.data.as_bytes());
}
}
LUAU_ASSERT!((self.main_function as usize) < self.functions.len());
write_var_int(&mut bytecode, self.main_function as u64);
self.bytecode = bytecode;
}
}