pub struct StringBuffer<'a>(/* private fields */);Expand description
Buffer that allows building Lua strings incrementally.
Construction of the string is done by calling the various StringBuffer::add_* methods to append text or data to the buffer.
Once complete, the resulting string can be pushed onto the stack by calling StringBuffer::push_result.
The buffer internally utilizes the stack in an unspecified way until completion,
resulting in the LuaState being mutably borrowed until the StringBuffer is dropped
(you can still access the LuaState using StringBuffer::lua).
The buffer will however not pop any element that was pushed prior to itself.
§Creation
A few steps are necessary to properly create a StringBuffer:
- It has to be initialized by the C API itself rather than by Rust (see
LuaState::init_buffer). - Before being initialized, it has to be pinned. (The buffer is self-referential, thus moving it would quickly result in undefined behavior.)
See below for some examples on how to create a buffer.
§Examples
Storing the buffer on the stack using pin! (recommended):
use core::pin::pin;
use low_luajit::{AmountReturned, LuaState, StringBuffer};
extern "C-unwind" fn example(mut lua: LuaState) -> AmountReturned {
let buffer = pin!(StringBuffer::uninit());
let mut buffer = lua.init_buffer(buffer);
// (Use the buffer in some way...)
buffer.push_result();
lua.return_any(1)
}Storing the buffer on the heap using a Box:
use low_luajit::{AmountReturned, LuaState, StringBuffer};
extern "C-unwind" fn example_box(mut lua: LuaState) -> AmountReturned {
let mut buffer = Box::pin(StringBuffer::uninit());
let mut buffer = lua.init_buffer(buffer.as_mut());
// (Use the buffer in some way...)
buffer.push_result();
lua.return_any(1)
}Unless Box’s features are required,
pin! should be preferred as it tends to be cheaper to use.
Implementations§
Source§impl StringBuffer<'_>
impl StringBuffer<'_>
Sourcepub const BUFFER_AREA_SIZE: usize = ffi::LUAL_BUFFERSIZE
pub const BUFFER_AREA_SIZE: usize = ffi::LUAL_BUFFERSIZE
The size of the “buffer area” used internally by StringBuffer.
This size may vary across compilation targets.
To access the buffer area directly, see StringBuffer::flush_buffer.
Sourcepub const fn uninit() -> MaybeUninit<Self>
pub const fn uninit() -> MaybeUninit<Self>
Returns the StringBuffer in an unitialized state.
Before it can be utilized, the buffer has to be initialized by LuaState::init_buffer.
Sourcepub fn as_mut_ptr(self: &mut Pin<&mut Self>) -> *mut luaL_Buffer
pub fn as_mut_ptr(self: &mut Pin<&mut Self>) -> *mut luaL_Buffer
Returns a mutable pointer to the wrapped luaL_Buffer.
This can be used to pass this StringBuffer to raw ffi functions.
The caller must ensure that the StringBuffer outlives the pointer this function returns, or else it will end up dangling.
Sourcepub fn add_char(self: &mut Pin<&mut Self>, ch: char)
pub fn add_char(self: &mut Pin<&mut Self>, ch: char)
Appends the given character ch to the buffer.
Sourcepub fn add_string(self: &mut Pin<&mut Self>, string: impl AsRef<[u8]>)
pub fn add_string(self: &mut Pin<&mut Self>, string: impl AsRef<[u8]>)
Appends a copy of the given string to the buffer.
As an alternative syntax, the += operation can be used instead.
Sourcepub fn add_byte_string(self: &mut Pin<&mut Self>, byte_string: &[u8])
pub fn add_byte_string(self: &mut Pin<&mut Self>, byte_string: &[u8])
Appends a copy of the given byte_string to the buffer.
Sourcepub fn add_cstring(self: &mut Pin<&mut Self>, cstring: &CStr)
pub fn add_cstring(self: &mut Pin<&mut Self>, cstring: &CStr)
Appends a copy of the given cstring to the buffer.
Sourcepub fn add_value(self: &mut Pin<&mut Self>, f: impl FnOnce(&mut LuaState))
pub fn add_value(self: &mut Pin<&mut Self>, f: impl FnOnce(&mut LuaState))
Appends the value at the top of the stack to the buffer.
The value should be pushed onto the stack by the given function f.
Only strings or numbers are accepted. Anything else will be discarded.
§Panics
Panics if the amount of elements present in the stack after f is called does not increase by a single element.
While replacing the elements pushed by the StringBuffer itself is possible and won’t cause a panic,
it’s still considered a logic error and it will likely cause a Lua error once StringBuffer::push_result is called.
Sourcepub fn add_size<'a>(
self: &'a mut Pin<&mut Self>,
amount: usize,
fill: u8,
) -> &'a mut [u8] ⓘ
pub fn add_size<'a>( self: &'a mut Pin<&mut Self>, amount: usize, fill: u8, ) -> &'a mut [u8] ⓘ
Appends the next amount bytes in the buffer area to the buffer.
This is done by initializing the bytes to fill and then returning a mutable slice to said bytes, to allow further modifications.
To instead simply mark the next amount of bytes as used, without initialization, see StringBuffer::add_size_unchecked.
§Panics
Panics if amount is greater than the size of the buffer area (see StringBuffer::BUFFER_AREA_SIZE).
Sourcepub unsafe fn add_size_unchecked(self: &mut Pin<&mut Self>, amount: usize)
pub unsafe fn add_size_unchecked(self: &mut Pin<&mut Self>, amount: usize)
Appends the next amount bytes in the buffer area to the buffer.
This is done by simply increasing the amount of the area marked as used by amount, without doing any checks.
For safer version of this function, see StringBuffer::add_size.
§Safety
The next amount bytes in the buffer area must be initialized and not out of bounds.
See StringBuffer::flush_buffer for details on how to access and initialize the buffer area.
Sourcepub fn flush_buffer<'a>(
self: &'a mut Pin<&mut Self>,
) -> &'a mut [MaybeUninit<u8>; 8192]
pub fn flush_buffer<'a>( self: &'a mut Pin<&mut Self>, ) -> &'a mut [MaybeUninit<u8>; 8192]
Flushes the contents of the buffer onto the stack (in an unspecified way), returning a mutable reference to the array used internally by the buffer (the “buffer area”).
It is unspecified whether any bytes in the array are initialized or not, some may contain remnants of the flushed data.
Any data written directly to the array will not be appended to the buffer unless StringBuffer::add_size_unchecked is called afterwards.
(The data will otherwise be overwritten by the other methods or discarded.)
The size of the array may vary across compilation targets.
Sourcepub fn push_result(self: &mut Pin<&mut Self>)
pub fn push_result(self: &mut Pin<&mut Self>)
Pushes the entire Lua string onto the stack as a single element, completing it’s construction.
Unlike all other StringBuffer methods, this function leaves the stack in a well defined state:
only the finalized string remains, alongside any element present before the buffer was created.
After calling this function, the completed string can be returned to the caller by using LuaState::return_any.
Alternatively, it is possible to just continue appending more data to the finalized string using the StringBuffer::add_* methods
(you will have to call this function again afterwards).
§Lua Errors
If any element that was previously pushed by the buffer (before calling this function) has been manually replaced
(via either StringBuffer::add_value or StringBuffer::lua) to an invalid value, this function will most likely error.
Sourcepub unsafe fn return_result(self: Pin<&mut Self>) -> AmountReturned
pub unsafe fn return_result(self: Pin<&mut Self>) -> AmountReturned
Finishes the currently called CFunction, returning the completed string to the caller.
This function has the same caveats as StringBuffer::push_result.
§Safety
The returned AmountReturned must not be invalidated.
(There is currently no way to enforce this, hence the function’s unsafeness.)
This function’s behavior may be changed in the future once a way to make this function safe is found.
Sourcepub fn lua<T>(
self: &mut Pin<&mut Self>,
f: impl FnOnce(&mut LuaState) -> T,
) -> T
pub fn lua<T>( self: &mut Pin<&mut Self>, f: impl FnOnce(&mut LuaState) -> T, ) -> T
Temporarily grants access to the borrowed LuaState to the given function f,
returning whatever f returns.
As the stack might have grown in an unspecified way, you should not assume on the size or top elements of the stack.
§Panics
Panics if the amounts of elements present in the stack after f is called is not the same as the amount before f was called.
While replacing the elements pushed by the StringBuffer itself is possible and won’t cause a panic,
it’s still considered a logic error and it will likely cause a Lua error once StringBuffer::push_result is called.
Trait Implementations§
Source§impl<T: AsRef<[u8]>> AddAssign<T> for Pin<&mut StringBuffer<'_>>
impl<T: AsRef<[u8]>> AddAssign<T> for Pin<&mut StringBuffer<'_>>
Source§fn add_assign(&mut self, rhs: T)
fn add_assign(&mut self, rhs: T)
Behaves the same as StringBuffer::add_string.