mlua/
buffer.rs

1#[cfg(feature = "serde")]
2use serde::ser::{Serialize, Serializer};
3
4use crate::types::ValueRef;
5
6/// A Luau buffer type.
7///
8/// See the buffer [documentation] for more information.
9///
10/// [documentation]: https://luau.org/library#buffer-library
11#[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    /// Copies the buffer data into a new `Vec<u8>`.
18    pub fn to_vec(&self) -> Vec<u8> {
19        unsafe { self.as_slice().to_vec() }
20    }
21
22    /// Returns the length of the buffer.
23    pub fn len(&self) -> usize {
24        unsafe { self.as_slice().len() }
25    }
26
27    /// Returns `true` if the buffer is empty.
28    pub fn is_empty(&self) -> bool {
29        self.len() == 0
30    }
31
32    /// Reads given number of bytes from the buffer at the given offset.
33    ///
34    /// Offset is 0-based.
35    #[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    /// Writes given bytes to the buffer at the given offset.
44    ///
45    /// Offset is 0-based.
46    #[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}