Skip to main content

StringBuffer

Struct StringBuffer 

Source
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<'_>

Source

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.

Source

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.

Source

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.

Source

pub fn add_byte(self: &mut Pin<&mut Self>, byte: u8)

Appends the given byte to the buffer.

Source

pub fn add_char(self: &mut Pin<&mut Self>, ch: char)

Appends the given character ch to the buffer.

Source

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.

Source

pub fn add_byte_string(self: &mut Pin<&mut Self>, byte_string: &[u8])

Appends a copy of the given byte_string to the buffer.

Source

pub fn add_cstring(self: &mut Pin<&mut Self>, cstring: &CStr)

Appends a copy of the given cstring to the buffer.

Source

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.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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<'_>>

Source§

fn add_assign(&mut self, rhs: T)

Behaves the same as StringBuffer::add_string.

Source§

impl<'a> Debug for StringBuffer<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> !Send for StringBuffer<'a>

§

impl<'a> !Sync for StringBuffer<'a>

§

impl<'a> !Unpin for StringBuffer<'a>

§

impl<'a> !UnwindSafe for StringBuffer<'a>

§

impl<'a> Freeze for StringBuffer<'a>

§

impl<'a> RefUnwindSafe for StringBuffer<'a>

§

impl<'a> UnsafeUnpin for StringBuffer<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.