luaur-vm 0.1.0

The Luau register virtual machine and standard library (Rust).
Documentation
use crate::enums::lua_type::lua_Type;
use crate::functions::lua_checkstack::lua_checkstack;
use crate::functions::lua_l_checktype::lua_l_checktype;
use crate::functions::lua_l_error_l::lua_l_error_l;
use crate::functions::lua_l_optinteger::lua_l_optinteger;
use crate::functions::lua_objlen::lua_objlen;
use crate::functions::lua_rawgeti::lua_rawgeti;
use crate::macros::hvalue::hvalue;
use crate::macros::setobj_2_s::setobj2s;
use crate::type_aliases::lua_state::lua_State;

#[no_mangle]
pub unsafe fn tunpack(L: *mut lua_State) -> core::ffi::c_int {
    lua_l_checktype(L, 1, lua_Type::LUA_TTABLE as core::ffi::c_int);
    let t = hvalue!((*L).base);

    let i = lua_l_optinteger(L, 2, 1);
    let e = lua_objlen(L, 1);
    let e = lua_l_optinteger(L, 3, e);

    if i > e {
        return 0; // empty range
    }

    let mut n = (e as u32).wrapping_sub(i as u32); // number of elements minus 1 (avoid overflows)
    n = n.wrapping_add(1);
    if n >= core::ffi::c_int::MAX as u32 || lua_checkstack(L, n as core::ffi::c_int) == 0 {
        lua_l_error_l(
            L,
            c"too many results to unpack".as_ptr(),
            core::format_args!("too many results to unpack"),
        );
    }

    // fast-path: direct array-to-stack copy
    if i == 1 && (n as core::ffi::c_int) <= (*t).sizearray {
        for i_idx in 0..(n as core::ffi::c_int) {
            let src = (*t).array.add(i_idx as usize);
            let dst = (*L).top.offset(i_idx as isize);
            setobj2s!(L, dst, src);
        }
        (*L).top = (*L).top.offset(n as isize);
    } else {
        // push arg[i..e - 1] (to avoid overflows)
        let mut current_i = i;
        while current_i < e {
            lua_rawgeti(L, 1, current_i);
            current_i += 1;
        }
        lua_rawgeti(L, 1, e); // push last element
    }

    n as core::ffi::c_int
}