1#[cfg(feature = "serde")]
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 pub fn is_empty(&self) -> bool {
29 self.len() == 0
30 }
31
32 #[track_caller]
36 pub fn read_bytes<const N: usize>(&self, offset: usize) -> [u8; N] {
37 let data = unsafe { self.as_slice() };
38 let mut bytes = [0u8; N];
39 bytes.copy_from_slice(&data[offset..offset + N]);
40 bytes
41 }
42
43 #[track_caller]
47 pub fn write_bytes(&self, offset: usize, bytes: &[u8]) {
48 let data = unsafe {
49 let (buf, size) = self.as_raw_parts();
50 std::slice::from_raw_parts_mut(buf, size)
51 };
52 data[offset..offset + bytes.len()].copy_from_slice(bytes);
53 }
54
55 pub(crate) unsafe fn as_slice(&self) -> &[u8] {
56 let (buf, size) = self.as_raw_parts();
57 std::slice::from_raw_parts(buf, size)
58 }
59
60 #[cfg(feature = "luau")]
61 unsafe fn as_raw_parts(&self) -> (*mut u8, usize) {
62 let lua = self.0.lua.lock();
63 let mut size = 0usize;
64 let buf = ffi::lua_tobuffer(lua.ref_thread(), self.0.index, &mut size);
65 mlua_assert!(!buf.is_null(), "invalid Luau buffer");
66 (buf as *mut u8, size)
67 }
68
69 #[cfg(not(feature = "luau"))]
70 unsafe fn as_raw_parts(&self) -> (*mut u8, usize) {
71 unreachable!()
72 }
73}
74
75#[cfg(feature = "serde")]
76impl Serialize for Buffer {
77 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
78 serializer.serialize_bytes(unsafe { self.as_slice() })
79 }
80}
81
82#[cfg(feature = "luau")]
83impl crate::types::LuaType for Buffer {
84 const TYPE_ID: std::os::raw::c_int = ffi::LUA_TBUFFER;
85}