luaur_vm/functions/
lua_h_getn.rs1use crate::functions::lua_h_getnum::lua_h_getnum;
2use crate::macros::dummynode::dummynode;
3use crate::macros::getaboundary::getaboundary;
4use crate::macros::ttisnil::ttisnil;
5use crate::records::lua_node::LuaNode;
6use crate::records::lua_table::LuaTable;
7use crate::type_aliases::t_value::TValue;
8use core::ffi::c_int;
9use luaur_common::macros::luau_assert::LUAU_ASSERT;
10
11#[inline]
12unsafe fn maybesetaboundary(t: *mut LuaTable, boundary: c_int) {
13 if (*t).union.aboundary <= 0 {
14 (*t).union.aboundary = -boundary;
15 }
16}
17
18unsafe fn updateaboundary(t: *mut LuaTable, boundary: c_int) -> c_int {
19 if boundary < (*t).sizearray && ttisnil!((*t).array.add((boundary - 1) as usize)) {
20 if boundary >= 2 && !ttisnil!((*t).array.add((boundary - 2) as usize)) {
21 maybesetaboundary(t, boundary - 1);
22 return boundary - 1;
23 }
24 } else if boundary + 1 < (*t).sizearray
25 && !ttisnil!((*t).array.add(boundary as usize))
26 && ttisnil!((*t).array.add((boundary + 1) as usize))
27 {
28 maybesetaboundary(t, boundary + 1);
29 return boundary + 1;
30 }
31
32 0
33}
34
35#[allow(non_snake_case)]
36pub unsafe fn lua_h_getn(t: *mut LuaTable) -> c_int {
37 let boundary = getaboundary(t);
38
39 if boundary > 0 {
40 if !ttisnil!((*t).array.add(((*t).sizearray - 1) as usize))
41 && (*t).node == dummynode as *mut LuaNode
42 {
43 return (*t).sizearray;
44 }
45
46 if boundary < (*t).sizearray
47 && !ttisnil!((*t).array.add((boundary - 1) as usize))
48 && ttisnil!((*t).array.add(boundary as usize))
49 {
50 return boundary;
51 }
52
53 let foundboundary = updateaboundary(t, boundary);
54 if foundboundary > 0 {
55 return foundboundary;
56 }
57 }
58
59 let j = (*t).sizearray;
60
61 if j > 0 && ttisnil!((*t).array.add((j - 1) as usize)) {
62 let mut base: *mut TValue = (*t).array;
63 let mut rest = j;
64
65 while rest >> 1 != 0 {
66 let half = rest >> 1;
67 if !ttisnil!(base.add(half as usize)) {
68 base = base.add(half as usize);
69 }
70 rest -= half;
71 }
72
73 let boundary = if !ttisnil!(base) { 1 } else { 0 } + base.offset_from((*t).array) as c_int;
74 maybesetaboundary(t, boundary);
75 boundary
76 } else {
77 LUAU_ASSERT!((*t).node == dummynode as *mut LuaNode || ttisnil!(lua_h_getnum(t, j + 1)));
78 j
79 }
80}
81
82#[export_name = "luaH_getn"]
83pub unsafe extern "C" fn lua_h_getn_export(t: *mut core::ffi::c_void) -> c_int {
84 lua_h_getn(t as *mut LuaTable)
85}
86
87#[allow(unused_imports)]
88pub use lua_h_getn as luaH_getn;