Skip to main content

luaur_vm/functions/
lua_s_buffinish.rs

1use crate::functions::lua_s_hash::luaS_hash;
2use crate::functions::lua_s_resize::luaS_resize;
3use crate::macros::atom_undef::ATOM_UNDEF;
4use crate::macros::lmod::lmod;
5use crate::macros::whitebits::WHITEBITS;
6use crate::records::gc_object::GCObject;
7use crate::records::stringtable::stringtable;
8use crate::records::t_string::TString;
9use crate::type_aliases::lua_state::lua_State;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12#[inline]
13unsafe fn same_bytes(a: *const core::ffi::c_char, b: *const core::ffi::c_char, len: usize) -> bool {
14    core::slice::from_raw_parts(a as *const u8, len)
15        == core::slice::from_raw_parts(b as *const u8, len)
16}
17
18#[allow(non_snake_case)]
19pub unsafe fn luaS_buffinish(l: *mut lua_State, ts: *mut TString) -> *mut TString {
20    let h = luaS_hash((*ts).data.as_ptr(), (*ts).len as usize);
21    let tb: *mut stringtable = core::ptr::addr_of_mut!((*(*l).global).strt);
22    let bucket = lmod!(h, (*tb).size) as i32;
23
24    let mut el = *(*tb).hash.add(bucket as usize);
25    while !el.is_null() {
26        if (*el).len == (*ts).len
27            && same_bytes((*el).data.as_ptr(), (*ts).data.as_ptr(), (*ts).len as usize)
28        {
29            if crate::isdead!((*l).global, el as *mut GCObject) {
30                (*el).hdr.marked ^= WHITEBITS as u8;
31            }
32            return el;
33        }
34        el = (*el).next;
35    }
36
37    LUAU_ASSERT!((*ts).next.is_null());
38
39    (*ts).hash = h;
40    *(*ts).data.as_mut_ptr().add((*ts).len as usize) = 0;
41    (*ts).atom = ATOM_UNDEF as i16;
42    (*ts).next = *(*tb).hash.add(bucket as usize);
43    *(*tb).hash.add(bucket as usize) = ts;
44
45    (*tb).nuse = (*tb).nuse.wrapping_add(1);
46    if (*tb).nuse > (*tb).size as u32 && (*tb).size <= core::ffi::c_int::MAX / 2 {
47        luaS_resize(l, (*tb).size * 2);
48    }
49
50    ts
51}
52
53#[allow(unused_imports)]
54pub use luaS_buffinish as lua_s_buffinish;