mlua/
buffer.rs

1#[cfg(feature = "serialize")]
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    #[doc(hidden)]
29    pub fn is_empty(&self) -> bool {
30        self.len() == 0
31    }
32
33    /// Reads given number of bytes from the buffer at the given offset.
34    ///
35    /// Offset is 0-based.
36    #[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    /// Writes given bytes to the buffer at the given offset.
45    ///
46    /// Offset is 0-based.
47    #[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}