1#[cfg(feature = "serialize")]
2use serde::ser::{Serialize, Serializer};
3
4use crate::types::ValueRef;
5
6#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
12#[derive(Clone, Debug, PartialEq)]
13pub struct Buffer(pub(crate) ValueRef);
14
15#[cfg_attr(not(feature = "luau"), allow(unused))]
16impl Buffer {
17 pub fn to_vec(&self) -> Vec<u8> {
19 unsafe { self.as_slice().to_vec() }
20 }
21
22 pub fn len(&self) -> usize {
24 unsafe { self.as_slice().len() }
25 }
26
27 #[doc(hidden)]
29 pub fn is_empty(&self) -> bool {
30 self.len() == 0
31 }
32
33 #[track_caller]
37 pub fn read_bytes<const N: usize>(&self, offset: usize) -> [u8; N] {
38 let data = unsafe { self.as_slice() };
39 let mut bytes = [0u8; N];
40 bytes.copy_from_slice(&data[offset..offset + N]);
41 bytes
42 }
43
44 #[track_caller]
48 pub fn write_bytes(&self, offset: usize, bytes: &[u8]) {
49 let data = unsafe {
50 let (buf, size) = self.as_raw_parts();
51 std::slice::from_raw_parts_mut(buf, size)
52 };
53 data[offset..offset + bytes.len()].copy_from_slice(bytes);
54 }
55
56 pub(crate) unsafe fn as_slice(&self) -> &[u8] {
57 let (buf, size) = self.as_raw_parts();
58 std::slice::from_raw_parts(buf, size)
59 }
60
61 #[cfg(feature = "luau")]
62 unsafe fn as_raw_parts(&self) -> (*mut u8, usize) {
63 let lua = self.0.lua.lock();
64 let mut size = 0usize;
65 let buf = ffi::lua_tobuffer(lua.ref_thread(), self.0.index, &mut size);
66 mlua_assert!(!buf.is_null(), "invalid Luau buffer");
67 (buf as *mut u8, size)
68 }
69
70 #[cfg(not(feature = "luau"))]
71 unsafe fn as_raw_parts(&self) -> (*mut u8, usize) {
72 unreachable!()
73 }
74}
75
76#[cfg(feature = "serialize")]
77impl Serialize for Buffer {
78 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
79 serializer.serialize_bytes(unsafe { self.as_slice() })
80 }
81}
82
83#[cfg(feature = "luau")]
84impl crate::types::LuaType for Buffer {
85 const TYPE_ID: std::os::raw::c_int = ffi::LUA_TBUFFER;
86}