luaur_vm/functions/
buffer_writefp.rs1use luaur_common::macros::luau_big_endian::LUAU_BIG_ENDIAN;
2
3use crate::functions::buffer_swapbe::buffer_swapbe;
4use crate::functions::lua_l_checkbuffer::lua_l_checkbuffer;
5use crate::functions::lua_l_checkinteger::lua_l_checkinteger;
6use crate::functions::lua_l_checknumber::lua_l_checknumber;
7use crate::macros::isoutofbounds::isoutofbounds;
8use crate::macros::lua_l_error::luaL_error;
9use crate::type_aliases::lua_state::lua_State;
10
11#[allow(non_snake_case)]
12pub unsafe fn buffer_writefp<T, StorageType>(L: *mut lua_State) -> core::ffi::c_int
13where
14 T: Copy + BufferFloat,
15 StorageType: Copy,
16{
17 let mut len: usize = 0;
18 let buf = lua_l_checkbuffer(L, 1, &mut len);
19
20 let offset = lua_l_checkinteger(L, 2);
21 let value = lua_l_checknumber(L, 3);
22
23 if isoutofbounds(offset, len, core::mem::size_of::<T>()) {
24 luaL_error!(L, "buffer access out of bounds");
25 }
26
27 let val: T = T::from_f64(value);
28
29 if LUAU_BIG_ENDIAN {
30 static_assert_size_match::<T, StorageType>();
31 let mut tmp: StorageType =
32 core::ptr::read_unaligned(&val as *const T as *const StorageType);
33 tmp = buffer_swapbe(tmp);
34 core::ptr::copy_nonoverlapping(
35 &tmp as *const StorageType as *const u8,
36 (buf as *mut u8).add(offset as usize),
37 core::mem::size_of::<StorageType>(),
38 );
39 } else {
40 core::ptr::copy_nonoverlapping(
41 &val as *const T as *const u8,
42 (buf as *mut u8).add(offset as usize),
43 core::mem::size_of::<T>(),
44 );
45 }
46
47 0
48}
49
50#[allow(dead_code)]
52fn static_assert_size_match<T, StorageType>() {
53 assert!(core::mem::size_of::<T>() == core::mem::size_of::<StorageType>());
54}
55
56pub trait BufferFloat {
57 fn from_f64(value: f64) -> Self;
58}
59
60impl BufferFloat for f32 {
61 fn from_f64(value: f64) -> Self {
62 value as f32
63 }
64}
65
66impl BufferFloat for f64 {
67 fn from_f64(value: f64) -> Self {
68 value
69 }
70}