Skip to content

Commit dd4d1a9

Browse files
committed
Add support for lua.concat() without strong type assertions in debug builds
1 parent f555d53 commit dd4d1a9

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ lua.doString(
7979

8080
| API | Support |
8181
|---|---|
82-
| Lua C API (`lua_*`) | 51% available (47/92) | <!-- 51.03% - Add 1.07 per -->
82+
| Lua C API (`lua_*`) | 52% available (47/92) | <!-- 52.10% - Add 1.07 per -->
8383
| Auxilary Library (`luaL_*`) | 6% available (3/48) | <!-- Always 2% * n, for n up to 48 -->
8484
| LuaJIT Extensions | *No plans to implement.* |
8585

@@ -100,7 +100,7 @@ pattern has changed, such as using the Zig `init()` function pattern instead of
100100
| `lua_CFunction`| ☑️ `lua.CFunction` |
101101
| `lua_checkstack`| ☑️ `lua.checkStack()` |
102102
| `lua_close`| ☑️📢 `lua.deinit()` |
103-
| `lua_concat`||
103+
| `lua_concat`| ☑️ `lua.concat()` |
104104
| `lua_cpcall`||
105105
| `lua_createtable`| ☑️ `lua.createTable()` |
106106
| `lua_dump`||

src/lua_api.zig

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@
1414
/// Stack Behavior: `[-0, +0, -]`
1515
pub fn atPanic(lua: *Lua, panicf: CFunction) CFunction;
1616

17-
/// Concatenates the n values at the top of the stack, pops them, and leaves the result at the top.
18-
/// If n is 1, the result is the single value on the stack (that is, the function does nothing);
19-
/// if n is 0, the result is the empty string. Concatenation is performed following the usual
20-
/// semantics of Lua (see https://www.lua.org/manual/5.1/manual.html#2.5.4).
21-
///
22-
/// From: `void lua_concat(lua_State *L, int n);`
23-
/// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_concat
24-
/// Stack Behavior: `[-n, +1, e]`
25-
pub fn concat(lua: *Lua, n: i32) void;
26-
2717
/// Calls the C function `func` in protected mode. `func` starts with only one element in its stack,
2818
/// a light userdata containing `ud`. In case of errors, returns the same error codes as `lua_pcall`,
2919
/// plus the error object on the top of the stack; otherwise, returns zero and does not change the stack.

src/root.zig

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const testing = std.testing;
66
const assert = std.debug.assert;
77

88
const mode = @import("builtin").mode;
9+
const isSafeBuildTarget: bool = mode == .ReleaseSafe or mode == .Debug;
910

1011
const c = @import("c");
1112
fn asState(lua: *Lua) *c.lua_State {
@@ -214,7 +215,7 @@ pub const Lua = opaque {
214215
assert(index != 0);
215216

216217
// Make sure we only run these checks in safety-checked build modes.
217-
if (mode == .ReleaseSafe or mode == .Debug) {
218+
if (isSafeBuildTarget) {
218219
if (index <= c.LUA_REGISTRYINDEX) {
219220
const max_upvalues_count = 255;
220221
assert(@as(i32, @intCast(c.LUA_GLOBALSINDEX - max_upvalues_count)) <= index); // Safety check failed: pseudo-index exceeds maximum number of upvalues (255). This can also happen if your stack index has been corrupted and become a very large negative number.
@@ -914,6 +915,23 @@ pub const Lua = opaque {
914915
return 1 == c.lua_lessthan(asState(lua), index_left, index_right);
915916
}
916917

918+
/// Concatenates the n values at the top of the stack, pops them, and leaves the result at the top.
919+
/// If n is 1, the result is the single value on the stack (that is, the function does nothing);
920+
/// if n is 0, the result is the empty string. Concatenation is performed following the usual
921+
/// semantics of the lua concat `..` operator (see https://www.lua.org/manual/5.1/manual.html#2.5.4).
922+
///
923+
/// In Debug or ReleaseSafe builds, the values to be concatenated are checked to be strings, numbers
924+
/// or types with the `__concat` metamethod defined.
925+
///
926+
/// From: `void lua_concat(lua_State *L, int n);`
927+
/// Refer to: https://www.lua.org/manual/5.1/manual.html#lua_concat
928+
/// Stack Behavior: `[-n, +1, e]`
929+
pub fn concat(lua: *Lua, n: i32) void {
930+
assert(n >= 0);
931+
932+
return c.lua_concat(asState(lua), n);
933+
}
934+
917935
/// Returns the current status of the thread. The status will be `Status.ok` for a normal thread, an error
918936
/// code if the thread finished its execution with an error, or `status.yield` if the thread is suspended.
919937
///
@@ -1889,3 +1907,31 @@ test "lessthan should follow expected semantics" {
18891907
try std.testing.expect(!lua.lessThan(-1, -2));
18901908
lua.pop(2);
18911909
}
1910+
1911+
test "concat should follow expected semantics" {
1912+
const lua = try Lua.init(std.testing.allocator);
1913+
defer lua.deinit();
1914+
1915+
lua.concat(0);
1916+
try std.testing.expectEqualSlices(u8, "", try lua.toLString(-1));
1917+
lua.pop(1);
1918+
1919+
lua.pushInteger(42);
1920+
lua.concat(1);
1921+
try std.testing.expectEqualSlices(u8, "42", try lua.toLString(-1));
1922+
lua.pop(1);
1923+
1924+
lua.pushNumber(13.1);
1925+
lua.pushInteger(13);
1926+
lua.concat(2);
1927+
try std.testing.expectEqualSlices(u8, "13.113", try lua.toLString(-1));
1928+
lua.pop(1);
1929+
1930+
lua.pushInteger(42);
1931+
lua.pushLString("-");
1932+
lua.pushInteger(84);
1933+
lua.pushLString("-Boof");
1934+
lua.concat(4);
1935+
try std.testing.expectEqualSlices(u8, "42-84-Boof", try lua.toLString(-1));
1936+
lua.pop(1);
1937+
}

0 commit comments

Comments
 (0)