Skip to content

Commit 25ebb59

Browse files
committed
Make toNumber and toInteger always return error union
Lua 5.1 is the only target version that does not include a tointegerx. Rather than make a separate function with a return type, this unifies the two functions so that an error union is always possible. Making function use between lua versions more consistent.
1 parent e8a26b0 commit 25ebb59

File tree

2 files changed

+55
-99
lines changed

2 files changed

+55
-99
lines changed

src/lib.zig

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,45 +1904,41 @@ pub const Lua = opaque {
19041904
c.lua_toclose(@ptrCast(lua), index);
19051905
}
19061906

1907-
fn toInteger51(lua: *Lua, index: i32) Integer {
1908-
return c.lua_tointeger(@ptrCast(lua), index);
1909-
}
1910-
1911-
fn toInteger52(lua: *Lua, index: i32) !Integer {
1912-
var success: c_int = undefined;
1913-
const result = c.lua_tointegerx(@ptrCast(lua), index, &success);
1914-
if (success == 0) return error.Fail;
1915-
return result;
1916-
}
1917-
19181907
/// Converts the Lua value at the given `index` to a signed integer
19191908
/// The Lua value must be an integer, or a number, or a string convertible to an integer otherwise toIntegerX returns 0
19201909
/// Returns an error if the conversion failed
1921-
/// See https://www.lua.org/manual/5.4/manual.html#lua_tointeger
1922-
pub const toInteger = switch (lang) {
1923-
.lua51, .luajit => toInteger51,
1924-
else => toInteger52,
1925-
};
1926-
1927-
fn toNumber51(lua: *Lua, index: i32) Number {
1928-
return c.lua_tonumber(@ptrCast(lua), index);
1929-
}
1930-
1931-
fn toNumber52(lua: *Lua, index: i32) !Number {
1932-
var success: c_int = undefined;
1933-
const result = c.lua_tonumberx(@ptrCast(lua), index, &success);
1934-
if (success == 0) return error.Fail;
1935-
return result;
1910+
/// See https://www.lua.org/manual/5.4/manual.html#lua_tointeger'
1911+
pub fn toInteger(lua: *Lua, index: i32) !Integer {
1912+
switch (lang) {
1913+
.lua51 => {
1914+
return c.lua_tointeger(@ptrCast(lua), index);
1915+
},
1916+
else => {
1917+
var success: c_int = undefined;
1918+
const result = c.lua_tointegerx(@ptrCast(lua), index, &success);
1919+
if (success == 0) return error.Fail;
1920+
return result;
1921+
},
1922+
}
19361923
}
19371924

19381925
/// Converts the Lua value at the given `index` to a float
19391926
/// The Lua value must be a number or a string convertible to a number otherwise toNumberX returns 0
19401927
/// Returns an error if the conversion failed
19411928
/// See https://www.lua.org/manual/5.4/manual.html#lua_tonumber
1942-
pub const toNumber = switch (lang) {
1943-
.lua51, .luajit => toNumber51,
1944-
else => toNumber52,
1945-
};
1929+
pub fn toNumber(lua: *Lua, index: i32) !Number {
1930+
switch (lang) {
1931+
.lua51 => {
1932+
return c.lua_tonumber(@ptrCast(lua), index);
1933+
},
1934+
else => {
1935+
var success: c_int = undefined;
1936+
const result = c.lua_tonumberx(@ptrCast(lua), index, &success);
1937+
if (success == 0) return error.Fail;
1938+
return result;
1939+
},
1940+
}
1941+
}
19461942

19471943
/// Converts the value at the given `index` to an opaque pointer
19481944
/// See https://www.lua.org/manual/5.4/manual.html#lua_topointer
@@ -3155,28 +3151,12 @@ pub const Lua = opaque {
31553151

31563152
switch (@typeInfo(T)) {
31573153
.Int => {
3158-
switch (comptime lang) {
3159-
.lua51, .luajit => {
3160-
const result = lua.toInteger(index);
3161-
return @as(T, @intCast(result));
3162-
},
3163-
else => {
3164-
const result = try lua.toInteger(index);
3165-
return @as(T, @intCast(result));
3166-
},
3167-
}
3154+
const result = try lua.toInteger(index);
3155+
return @as(T, @intCast(result));
31683156
},
31693157
.Float => {
3170-
switch (comptime lang) {
3171-
.lua51, .luajit => {
3172-
const result = lua.toNumber(index);
3173-
return @as(T, @floatCast(result));
3174-
},
3175-
else => {
3176-
const result = try lua.toNumber(index);
3177-
return @as(T, @floatCast(result));
3178-
},
3179-
}
3158+
const result = try lua.toNumber(index);
3159+
return @as(T, @floatCast(result));
31803160
},
31813161
.Array, .Vector => {
31823162
const child = std.meta.Child(T);

src/tests.zig

Lines changed: 25 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,12 @@ fn expectStringContains(actual: []const u8, expected_contains: []const u8) !void
1818
return error.TestExpectedStringContains;
1919
}
2020

21-
// Helper functions
22-
//
23-
// For the most part, it is easy to test each Lua version simulataneously. Although each
24-
// version offers a different API, there are more similarities than differences. Using
25-
// ziglua.lang is usually enough to handle the differences. Some common functions like
26-
// toInteger differ enough to require these helper functions to handle the differences
27-
// to keep the test code more readable
28-
29-
// TODO: implement as much of this as is reasonable in the shared lib.zig and remove these
30-
3121
/// Return true if ziglua.lang matches any of the given langs
3222
inline fn langIn(langs: anytype) bool {
3323
inline for (langs) |lang| if (ziglua.lang == lang) return true;
3424
return false;
3525
}
3626

37-
/// toInteger that always returns an error union
38-
inline fn toInteger(lua: *Lua, index: i32) !ziglua.Integer {
39-
if (ziglua.lang == .lua51 or ziglua.lang == .luajit) {
40-
return lua.toInteger(index);
41-
} else return try lua.toInteger(index);
42-
}
43-
44-
/// toNumber that always returns an error union
45-
inline fn toNumber(lua: *Lua, index: i32) !ziglua.Number {
46-
if (ziglua.lang == .lua51 or ziglua.lang == .luajit) {
47-
return lua.toNumber(index);
48-
} else return try lua.toNumber(index);
49-
}
50-
5127
fn alloc(data: ?*anyopaque, ptr: ?*anyopaque, osize: usize, nsize: usize) callconv(.C) ?*anyopaque {
5228
_ = data;
5329

@@ -123,7 +99,7 @@ test "Zig allocator access" {
12399
fn inner(l: *Lua) i32 {
124100
const allocator = l.allocator();
125101

126-
const num = toInteger(l, 1) catch unreachable;
102+
const num = l.toInteger(1) catch unreachable;
127103

128104
// Use the allocator
129105
const nums = allocator.alloc(i32, @intCast(num)) catch unreachable;
@@ -143,7 +119,7 @@ test "Zig allocator access" {
143119
lua.pushInteger(10);
144120
try lua.protectedCall(1, 1, 0);
145121

146-
try expectEqual(45, try toInteger(lua, -1));
122+
try expectEqual(45, try lua.toInteger(-1));
147123
}
148124

149125
test "standard library loading" {
@@ -272,8 +248,8 @@ test "compare" {
272248

273249
const add = struct {
274250
fn addInner(l: *Lua) i32 {
275-
const a = toInteger(l, 1) catch 0;
276-
const b = toInteger(l, 2) catch 0;
251+
const a = l.toInteger(1) catch 0;
252+
const b = l.toInteger(2) catch 0;
277253
l.pushInteger(a + b);
278254
return 1;
279255
}
@@ -301,7 +277,7 @@ test "type of and getting values" {
301277
lua.pushInteger(1);
302278
try expectEqual(.number, lua.typeOf(-1));
303279
try expect(lua.isNumber(-1));
304-
try expectEqual(1, try toInteger(lua, -1));
280+
try expectEqual(1, try lua.toInteger(-1));
305281
try expectEqualStrings("number", lua.typeNameIndex(-1));
306282

307283
var value: i32 = 0;
@@ -313,7 +289,7 @@ test "type of and getting values" {
313289
lua.pushNumber(0.1);
314290
try expectEqual(.number, lua.typeOf(-1));
315291
try expect(lua.isNumber(-1));
316-
try expectEqual(0.1, try toNumber(lua, -1));
292+
try expectEqual(0.1, try lua.toNumber(-1));
317293

318294
_ = lua.pushThread();
319295
try expectEqual(.thread, lua.typeOf(-1));
@@ -388,7 +364,7 @@ test "executing string contents" {
388364
try lua.protectedCall(0, 0, 0);
389365

390366
try expectEqual(.number, try lua.getGlobal("a"));
391-
try expectEqual(12, try toInteger(lua, 1));
367+
try expectEqual(12, try lua.toInteger(1));
392368

393369
try expectError(if (ziglua.lang == .luau) error.Fail else error.Syntax, lua.loadString("bad syntax"));
394370
try lua.loadString("a = g()");
@@ -505,7 +481,7 @@ test "calling a function" {
505481

506482
// protectedCall is preferred, but we might as well test call when we know it is safe
507483
lua.call(2, 1);
508-
try expectEqual(42, try toInteger(lua, 1));
484+
try expectEqual(42, try lua.toInteger(1));
509485
}
510486

511487
test "calling a function with cProtectedCall" {
@@ -836,7 +812,7 @@ test "table access" {
836812

837813
_ = lua.pushStringZ("other one");
838814
try expectEqual(.number, lua.rawGetTable(1));
839-
try expectEqual(1234, try toInteger(lua, -1));
815+
try expectEqual(1234, try lua.toInteger(-1));
840816

841817
// a.name = "ziglua"
842818
_ = lua.pushStringZ("name");
@@ -984,7 +960,7 @@ test "dump and load" {
984960
// now call the new function (which should return the value + 5)
985961
lua.pushInteger(6);
986962
try lua.protectedCall(1, 1, 0);
987-
try expectEqual(11, try toInteger(lua, -1));
963+
try expectEqual(11, try lua.toInteger(-1));
988964
}
989965

990966
test "threads" {
@@ -1051,7 +1027,7 @@ test "upvalues" {
10511027
// counter from PIL
10521028
const counter = struct {
10531029
fn inner(l: *Lua) i32 {
1054-
var counter = toInteger(l, Lua.upvalueIndex(1)) catch 0;
1030+
var counter = l.toInteger(Lua.upvalueIndex(1)) catch 0;
10551031
counter += 1;
10561032
l.pushInteger(counter);
10571033
l.pushInteger(counter);
@@ -1070,7 +1046,7 @@ test "upvalues" {
10701046
while (expected <= 10) : (expected += 1) {
10711047
_ = try lua.getGlobal("counter");
10721048
lua.call(0, 1);
1073-
try expectEqual(expected, try toInteger(lua, -1));
1049+
try expectEqual(expected, try lua.toInteger(-1));
10741050
lua.pop(1);
10751051
}
10761052
}
@@ -1096,7 +1072,7 @@ test "table traversal" {
10961072
},
10971073
.number => {
10981074
try expectEqualStrings("third", try lua.toString(-2));
1099-
try expectEqual(1, try toInteger(lua, -1));
1075+
try expectEqual(1, try lua.toInteger(-1));
11001076
},
11011077
else => unreachable,
11021078
}
@@ -1456,25 +1432,25 @@ test "checkOption" {
14561432
lua.pushFunction(function);
14571433
_ = lua.pushStringZ("one");
14581434
try lua.protectedCall(1, 1, 0);
1459-
try expectEqual(1, try toInteger(lua, -1));
1435+
try expectEqual(1, try lua.toInteger(-1));
14601436
lua.pop(1);
14611437

14621438
lua.pushFunction(function);
14631439
_ = lua.pushStringZ("two");
14641440
try lua.protectedCall(1, 1, 0);
1465-
try expectEqual(2, try toInteger(lua, -1));
1441+
try expectEqual(2, try lua.toInteger(-1));
14661442
lua.pop(1);
14671443

14681444
lua.pushFunction(function);
14691445
_ = lua.pushStringZ("three");
14701446
try lua.protectedCall(1, 1, 0);
1471-
try expectEqual(3, try toInteger(lua, -1));
1447+
try expectEqual(3, try lua.toInteger(-1));
14721448
lua.pop(1);
14731449

14741450
// try the default now
14751451
lua.pushFunction(function);
14761452
try lua.protectedCall(0, 1, 0);
1477-
try expectEqual(1, try toInteger(lua, -1));
1453+
try expectEqual(1, try lua.toInteger(-1));
14781454
lua.pop(1);
14791455

14801456
// check the raised error
@@ -1515,7 +1491,7 @@ test "loadBuffer" {
15151491

15161492
try lua.protectedCall(0, ziglua.mult_return, 0);
15171493
_ = try lua.getGlobal("global");
1518-
try expectEqual(10, try toInteger(lua, -1));
1494+
try expectEqual(10, try lua.toInteger(-1));
15191495
}
15201496

15211497
test "where" {
@@ -1608,7 +1584,7 @@ test "metatables" {
16081584
}
16091585

16101586
try lua.callMeta(-1, "__len");
1611-
try expectEqual(10, try toNumber(lua, -1));
1587+
try expectEqual(10, try lua.toNumber(-1));
16121588
}
16131589

16141590
test "args and errors" {
@@ -1987,7 +1963,7 @@ test "debug interface Lua 5.1 and Luau" {
19871963
l.getInfo(.{ .l = true }, i);
19881964
if (i.current_line.? != 2) std.debug.panic("Expected line to be 2", .{});
19891965
_ = l.getLocal(i, 1) catch unreachable;
1990-
if ((l.toNumber(-1)) != 3) std.debug.panic("Expected x to equal 3", .{});
1966+
if ((l.toNumber(-1) catch unreachable) != 3) std.debug.panic("Expected x to equal 3", .{});
19911967
},
19921968
.line => if (i.current_line.? == 4) {
19931969
// modify the value of y to be 0 right before returning
@@ -1998,7 +1974,7 @@ test "debug interface Lua 5.1 and Luau" {
19981974
l.getInfo(.{ .l = true }, i);
19991975
if (i.current_line.? != 4) std.debug.panic("Expected line to be 4", .{});
20001976
_ = l.getLocal(i, 1) catch unreachable;
2001-
if ((l.toNumber(-1)) != 3) std.debug.panic("Expected result to equal 3", .{});
1977+
if ((l.toNumber(-1) catch unreachable) != 3) std.debug.panic("Expected result to equal 3", .{});
20021978
},
20031979
else => unreachable,
20041980
}
@@ -2038,7 +2014,7 @@ test "debug upvalues" {
20382014

20392015
// inspect the upvalue (should be x)
20402016
try expectEqualStrings(if (ziglua.lang == .luau) "" else "x", try lua.getUpvalue(-1, 1));
2041-
try expectEqual(1, try toNumber(lua, -1));
2017+
try expectEqual(1, try lua.toNumber(-1));
20422018
lua.pop(1);
20432019

20442020
// now make the function an "add five" function
@@ -2051,7 +2027,7 @@ test "debug upvalues" {
20512027
// call the new function (should return 7)
20522028
lua.pushNumber(2);
20532029
try lua.protectedCall(1, 1, 0);
2054-
try expectEqual(7, try toNumber(lua, -1));
2030+
try expectEqual(7, try lua.toNumber(-1));
20552031

20562032
if (langIn(.{ .lua51, .luajit, .luau })) return;
20572033

@@ -2565,12 +2541,12 @@ test "pushAny" {
25652541

25662542
//int
25672543
try lua.pushAny(1);
2568-
const my_int = try toInteger(lua, -1);
2544+
const my_int = try lua.toInteger(-1);
25692545
try testing.expect(my_int == 1);
25702546

25712547
//float
25722548
try lua.pushAny(1.0);
2573-
const my_float = try toNumber(lua, -1);
2549+
const my_float = try lua.toNumber(-1);
25742550
try testing.expect(my_float == 1.0);
25752551

25762552
//bool

0 commit comments

Comments
 (0)