luaur_vm/functions/
lua_s_buffinish.rs1use 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;