@@ -2483,9 +2483,7 @@ pub const Lua = opaque {
24832483 var ptr_copy = ptr ;
24842484
24852485 if (@intFromPtr (ptr ) >= @intFromPtr (& buffer .buffer ) + c .LUAL_BUFFERSIZE ) {
2486- const extra = c .luaL_prepbuffer (@ptrCast (buffer ));
2487- assert (extra != null );
2488- ptr_copy = extra ;
2486+ ptr_copy = buffer .prepBuffer ();
24892487 }
24902488
24912489 // We can assert buffer.p is non-null here since prepbuffer guarantees it
@@ -2499,6 +2497,48 @@ pub const Lua = opaque {
24992497 }
25002498 }
25012499
2500+ /// Prepares writable space in the buffer.
2501+ ///
2502+ /// Used to provide direct writing of data. The caller **MUST** call `buffer.addSize()` after writing content
2503+ /// to the returned address of memory. If you do not call `buffer.addSize()` then the content will not be added
2504+ /// to the result of the Buffer.
2505+ /// ```
2506+ /// var space = buffer.prepBuffer();
2507+ /// @memcpy(space, "Hello", 5);
2508+ /// buffer.addSize(5); // Required when directly writing
2509+ ///
2510+ /// Returns a pointer to space of size `BufferSize` bytes.
2511+ ///
2512+ /// From: `char *luaL_prepbuffer(luaL_Buffer *B);`
2513+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_prepbuffer
2514+ /// Stack Behavior: `[-0, +0, -]`
2515+ pub fn prepBuffer (buffer : * Buffer ) [* ]u8 {
2516+ assert (buffer .p != null and buffer .L != null ); // You must use `Lua.initBuffer(&Lua.Buffer)` before calling `Lua.Buffer.prepBuffer()`.
2517+
2518+ const ptr : ? [* ]u8 = @ptrCast (c .luaL_prepbuffer (@ptrCast (buffer )));
2519+ assert (ptr != null );
2520+ return ptr .? ;
2521+ }
2522+
2523+ /// Adds to the buffer a string of length `n` previously copied to the buffer area. Callers should write to the
2524+ /// buffer area returned from `prepBuffer()`.
2525+ ///
2526+ /// From: `void luaL_addsize(luaL_Buffer *B, size_t n);`
2527+ /// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_addsize
2528+ /// Stack Behavior: `[-0, +0, m]`
2529+ pub fn addSize (buffer : * Buffer , n : usize ) void {
2530+ assert (buffer .p != null and buffer .L != null ); // You must use `Lua.initBuffer(&Lua.Buffer)` before calling `Lua.Buffer.addSize()`.
2531+
2532+ if (buffer .p ) | ptr | {
2533+ buffer .p = ptr + n ;
2534+ } else {
2535+ std .debug .panic (
2536+ "Failed to buffer.addSize('{d}'): the buffer is not initialized, `buffer.p` is null.\n " ,
2537+ .{n },
2538+ );
2539+ }
2540+ }
2541+
25022542 /// Finishes the use of the buffer leaving the final string on the top of the stack.
25032543 ///
25042544 /// From: `void luaL_pushresult(luaL_Buffer *B);`
@@ -4789,3 +4829,28 @@ test "Buffer should handle very long string" {
47894829 try std .testing .expect (lua .isString (-1 ));
47904830 try std .testing .expectEqualStrings ("0123456789" ** 25_600 , try lua .toLString (-1 ));
47914831}
4832+
4833+ test "Buffer can be created by direct writes to the buffer" {
4834+ const lua = try Lua .init (std .testing .allocator );
4835+ defer lua .deinit ();
4836+
4837+ var b : Lua.Buffer = .{};
4838+ lua .initBuffer (& b );
4839+ var p = b .prepBuffer ();
4840+ p [0 ] = 'H' ;
4841+ p += 1 ;
4842+ p [0 ] = 'e' ;
4843+ p += 1 ;
4844+ p [0 ] = 'l' ;
4845+ p += 1 ;
4846+ p [0 ] = 'l' ;
4847+ p += 1 ;
4848+ p [0 ] = 'o' ;
4849+ p += 1 ;
4850+ b .addSize (5 );
4851+ b .pushResult ();
4852+
4853+ try std .testing .expectEqual (1 , lua .getTop ());
4854+ try std .testing .expect (lua .isString (-1 ));
4855+ try std .testing .expectEqualStrings ("Hello" , try lua .toLString (-1 ));
4856+ }
0 commit comments