luaur_vm/functions/
buffer_writebits.rs1use luaur_common::macros::luau_big_endian::LUAU_BIG_ENDIAN;
2
3use crate::functions::lua_l_checkbuffer::lua_l_checkbuffer;
4use crate::functions::lua_l_checkinteger::lua_l_checkinteger;
5use crate::functions::lua_l_checknumber::lua_l_checknumber;
6use crate::functions::lua_l_checkunsigned::lua_l_checkunsigned;
7use crate::macros::lua_l_error::luaL_error;
8use crate::type_aliases::lua_state::lua_State;
9
10pub fn buffer_writebits(L: *mut lua_State) -> core::ffi::c_int {
11 let mut len: usize = 0;
12 let buf = lua_l_checkbuffer(L, 1, &mut len) as *mut core::ffi::c_char;
13 let bitoffset = lua_l_checknumber(L, 2) as i64;
14 let bitcount = lua_l_checkinteger(L, 3);
15 let value = lua_l_checkunsigned(L, 4);
16
17 if bitoffset < 0 {
18 unsafe {
19 luaL_error!(L, "buffer access out of bounds");
20 }
21 }
22
23 if bitcount < 0 || bitcount > 32 {
24 unsafe {
25 luaL_error!(L, "bit count is out of range of [0; 32]");
26 }
27 }
28
29 if (bitoffset as u64 + bitcount as u64) > (len as u64) * 8 {
30 unsafe {
31 luaL_error!(L, "buffer access out of bounds");
32 }
33 }
34
35 let startbyte = (bitoffset / 8) as usize;
36 let endbyte = ((bitoffset + bitcount as i64 + 7) / 8) as usize;
37
38 let mut data: u64 = 0;
39
40 if LUAU_BIG_ENDIAN {
41 for i in (startbyte..endbyte).rev() {
42 data = data * 256 + (unsafe { *buf.add(i) } as u8) as u64;
43 }
44 } else {
45 unsafe {
46 core::ptr::copy_nonoverlapping(
47 buf.add(startbyte),
48 &mut data as *mut u64 as *mut core::ffi::c_char,
49 endbyte - startbyte,
50 );
51 }
52 }
53
54 let subbyteoffset = (bitoffset & 0x7) as u64;
55 let mask = (((1u64 << bitcount) - 1) << subbyteoffset) as u64;
56
57 data = (data & !mask) | (((value as u64) << subbyteoffset) & mask);
58
59 if LUAU_BIG_ENDIAN {
60 for i in startbyte..endbyte {
61 unsafe {
62 *buf.add(i) = (data & 0xff) as core::ffi::c_char;
63 }
64 data >>= 8;
65 }
66 } else {
67 unsafe {
68 core::ptr::copy_nonoverlapping(
69 &data as *const u64 as *const core::ffi::c_char,
70 buf.add(startbyte),
71 endbyte - startbyte,
72 );
73 }
74 }
75
76 0
77}