From ae0d079f9b1aeaef9b762a0e94f179ca43788e5e Mon Sep 17 00:00:00 2001 From: axdank Date: Mon, 2 Dec 2024 17:12:26 -0300 Subject: [PATCH 1/6] implement toTuple and others --- src/lib.zig | 136 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 7 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index a16a521..48fe4b3 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -585,6 +585,34 @@ pub fn Parsed(comptime T: type) type { }; } +const internals = [_][]const u8{ "toStruct", "toSlice", "toTuple", "toAnyInternal" }; + +// wrap over some internal functions of the Lua struct +pub const Internals = blk: { + const StructField = std.builtin.Type.StructField; + var fields: [internals.len]StructField = undefined; + for (internals, 0..) |entry, i| { + const F = @field(Lua, entry); + const T = @TypeOf(F); + fields[i] = .{ + .name = @ptrCast(entry), + .type = T, + .default_value = &F, + .is_comptime = false, + .alignment = @alignOf(T), + }; + } + + const TT = @Type(.{ .@"struct" = .{ + .layout = .auto, + .fields = &fields, + .decls = &.{}, + .is_tuple = false, + } }); + + break :blk TT{}; +}; + /// A Zig wrapper around the Lua C API /// Represents a Lua state or thread and contains the entire state of the Lua interpreter pub const Lua = opaque { @@ -4343,7 +4371,27 @@ pub const Lua = opaque { /// Works with ints, floats, booleans, structs, /// tagged unions, optionals, and strings pub fn pushAny(lua: *Lua, value: anytype) !void { - switch (@typeInfo(@TypeOf(value))) { + const T = @TypeOf(value); + const type_info = @typeInfo(T); + + if (type_info == .@"struct" or type_info == .@"union" or type_info == .@"enum") { + if (@hasDecl(T, "ziglua_pushAny")) { + const fnInfo = @typeInfo(@TypeOf(T.ziglua_pushAny)).@"fn"; + switch (fnInfo.params.len) { + // fn(self, lua) -> void + 2 => { + if (@typeInfo(fnInfo.return_type.?) == .error_union) { + return try value.ziglua_pushAny(lua); + } else { + return value.ziglua_pushAny(lua); + } + }, + else => @compileError(@typeName(T) ++ ".ziglua_pushAny has invalid signature, required: fn(self: T, lua: *Lua) void"), + } + } + } + + switch (type_info) { .int, .comptime_int => { lua.pushInteger(@intCast(value)); }, @@ -4398,10 +4446,18 @@ pub const Lua = opaque { }, .@"struct" => |info| { lua.createTable(0, 0); - inline for (info.fields) |field| { - try lua.pushAny(field.name); - try lua.pushAny(@field(value, field.name)); - lua.setTable(-3); + if (info.is_tuple) { + inline for (0..info.fields.len) |i| { + try lua.pushAny(i + 1); + try lua.pushAny(value[i]); + lua.setTable(-3); + } + } else { + inline for (info.fields) |field| { + try lua.pushAny(field.name); + try lua.pushAny(@field(value, field.name)); + lua.setTable(-3); + } } }, .@"union" => |info| { @@ -4468,7 +4524,26 @@ pub const Lua = opaque { } } - switch (@typeInfo(T)) { + const type_info = @typeInfo(T); + + if (type_info == .@"struct" or type_info == .@"union" or type_info == .@"enum") { + if (@hasDecl(T, "ziglua_toAny")) { + const fnInfo = @typeInfo(@TypeOf(T.ziglua_toAny)).@"fn"; + switch (fnInfo.params.len) { + // fn(lua_state, alloc, allow_alloc, index) -> T + 4 => { + if (@typeInfo(fnInfo.return_type.?) == .error_union) { + return try T.ziglua_toAny(lua, a, allow_alloc, index); + } else { + return T.ziglua_toAny(lua, a, allow_alloc, index); + } + }, + else => @compileError(@typeName(T) ++ ".ziglua_toAny has invalid signature, required: fn(lua: *Lua, alloc: ?std.mem.Allocator, comptime allow_alloc: bool, index: i32) T"), + } + } + } + + switch (type_info) { .int => { const result = try lua.toInteger(index); return @as(T, @intCast(result)); @@ -4542,7 +4617,11 @@ pub const Lua = opaque { return error.LuaInvalidEnumTagName; }, .@"struct" => { - return try lua.toStruct(T, a, allow_alloc, index); + if (type_info.@"struct".is_tuple) { + return try lua.toTuple(T, a, allow_alloc, index); + } else { + return try lua.toStruct(T, a, allow_alloc, index); + } }, .@"union" => |u| { if (u.tag_type == null) @compileError("Parameter type is not a tagged union"); @@ -4608,6 +4687,49 @@ pub const Lua = opaque { return result; } + /// Converts value at given index to a zig struct tuple if possible + fn toTuple(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, raw_index: i32) !T { + const stack_size_on_entry = lua.getTop(); + defer std.debug.assert(lua.getTop() == stack_size_on_entry); + + const info = @typeInfo(T).@"struct"; + const index = lua.absIndex(raw_index); + + var result: T = undefined; + + if (lua.isTable(index)) { + lua.pushValue(index); + defer lua.pop(1); + + inline for (info.fields, 0..) |field, i| { + if (lua.getMetaField(-1, "__index")) |_| { + lua.pushValue(-2); + lua.pushInteger(@intCast(i + 1)); + lua.call(.{ .args = 1, .results = 1 }); + } else |_| { + _ = lua.rawGetIndex(-1, @intCast(i + 1)); + } + defer lua.pop(1); + result[i] = try lua.toAnyInternal(field.type, a, allow_alloc, -1); + } + } else { + // taking it as vararg + const in_range = if (raw_index < 0) (index - @as(i32, info.fields.len)) >= 0 else ((index + @as(i32, info.fields.len)) - 1) <= stack_size_on_entry; + if (in_range) { + inline for (info.fields, 0..) |field, i| { + const stack_size_before_call = lua.getTop(); + const idx = if (raw_index < 0) index - @as(i32, @intCast(i)) else index + @as(i32, @intCast(i)); + result[i] = try lua.toAnyInternal(field.type, a, allow_alloc, idx); + std.debug.assert(stack_size_before_call == lua.getTop()); + } + } else { + return error.NotInRange; + } + } + + return result; + } + /// Converts value at given index to a zig struct if possible fn toStruct(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, raw_index: i32) !T { const stack_size_on_entry = lua.getTop(); From cd4d20b1dea8864c7ea97b01662692c4f6e98896 Mon Sep 17 00:00:00 2001 From: axdank Date: Mon, 2 Dec 2024 17:13:34 -0300 Subject: [PATCH 2/6] add tests for the new implementations --- src/tests.zig | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/src/tests.zig b/src/tests.zig index d9ff381..b0111c3 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -2382,6 +2382,91 @@ test "toAny struct" { )); } +test "toAny tuple from vararg" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + const Tuple = std.meta.Tuple(&.{ i32, bool, i32 }); + + lua.pushInteger(100); + lua.pushBoolean(true); + lua.pushInteger(300); + + const result = try lua.toAny(Tuple, 1); + try testing.expect(std.meta.eql(result, .{ 100, true, 300 })); + + const result_reverse = try lua.toAny(Tuple, -1); + try testing.expect(std.meta.eql(result_reverse, .{ 300, true, 100 })); + + const result_error = lua.toAny(Tuple, 2); + try testing.expectError(error.NotInRange, result_error); + + const result_reverse_error = lua.toAny(Tuple, -2); + try testing.expectError(error.NotInRange, result_reverse_error); +} + +test "toAny tuple from struct" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + const MyType = struct { + foo: i32, + bar: bool, + tuple: std.meta.Tuple(&.{ i32, bool, struct { foo: bool } }), + }; + + try lua.doString( + \\ value = { + \\ ["foo"] = 10, + \\ ["bar"] = false, + \\ ["tuple"] = {100, false, {["foo"] = true}} + \\ } + ); + + const lua_type = try lua.getGlobal("value"); + try testing.expect(lua_type == .table); + const my_struct = try lua.toAny(MyType, 1); + try testing.expect(std.meta.eql( + my_struct, + MyType{ .foo = 10, .bar = false, .tuple = .{ 100, false, .{ .foo = true } } }, + )); +} + +test "toAny from struct with custom toAny" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + const MyType = struct { + foo: bool, + bar: struct { + const Self = @This(); + foo: i32, + + pub fn ziglua_toAny(l: *Lua, a: ?std.mem.Allocator, comptime aa: bool, i: i32) !Self { + return try ziglua.Internals.toStruct(l, Self, a, aa, i); + } + }, + }; + + try lua.doString( + \\ value = { + \\ ["foo"] = true, + \\ ["bar"] = { + \\ ["foo"] = 12 + \\ } + \\ } + ); + + const lua_type = try lua.getGlobal("value"); + try testing.expect(lua_type == .table); + const my_struct = try lua.toAny(MyType, 1); + lua.pop(-1); + try testing.expect(std.meta.eql( + my_struct, + MyType{ .foo = true, .bar = .{ .foo = 12 } }, + )); +} + test "toAny mutable string" { var lua = try Lua.init(testing.allocator); defer lua.deinit(); @@ -2591,6 +2676,49 @@ test "pushAny struct" { try testing.expect(value.bar == (MyType{}).bar); } +test "pushAny tuple" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + const Tuple = std.meta.Tuple(&.{ i32, bool, i32 }); + const value: Tuple = .{ 500, false, 600 }; + + try lua.pushAny(value); + + const result = try lua.toAny(Tuple, 1); + try testing.expect(std.meta.eql(result, .{ 500, false, 600 })); +} + +test "pushAny from struct with custom pushAny" { + var lua = try Lua.init(testing.allocator); + defer lua.deinit(); + + const MyType = struct { + const Self = @This(); + foo: i32, + tuple: std.meta.Tuple(&.{ i32, i32 }), + + pub fn ziglua_pushAny(self: *const Self, l: *Lua) !void { + l.newTable(); + + inline for (@typeInfo(Self).@"struct".fields) |f| { + try l.pushAny(f.name); + try l.pushAny(@field(self, f.name)); + l.setTable(-3); + } + } + }; + + const value: MyType = .{ .foo = 15, .tuple = .{ 1, 2 } }; + + try lua.pushAny(value); + const my_struct = try lua.toAny(MyType, 1); + try testing.expect(std.meta.eql( + my_struct, + MyType{ .foo = 15, .tuple = .{ 1, 2 } }, + )); +} + test "pushAny tagged union" { var lua = try Lua.init(testing.allocator); defer lua.deinit(); From a47c1c8d21fe876613ce20b9ba8ba187c7dc61ea Mon Sep 17 00:00:00 2001 From: axdank Date: Tue, 3 Dec 2024 22:58:52 -0300 Subject: [PATCH 3/6] changes ziglua_{toAny, pushAny} to `fromLua` and `toLua` --- src/lib.zig | 130 ++++++++++++++++++++++++++++++++++++++++++++++---- src/tests.zig | 11 ++--- 2 files changed, 126 insertions(+), 15 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index 48fe4b3..743f2f5 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -4391,6 +4391,70 @@ pub const Lua = opaque { } } + if (type_info == .@"struct" or type_info == .@"union" or type_info == .@"enum") { + if (@hasDecl(T, "toLua")) { + const toLuaArgs = .{ value, lua }; + const fnSignature = comptime fn_sign: { + var b: []const u8 = "pub fn toLua("; + + for (0..toLuaArgs.len) |i| { + b = b ++ std.fmt.comptimePrint("{s}{s}", .{ @typeName(@TypeOf(toLuaArgs[i])), if (i == (toLuaArgs.len - 1)) "" else ", " }); + } + + b = b ++ ") !void"; + + break :fn_sign b; + }; + + const fl = @field(T, "toLua"); + const flt = @TypeOf(fl); + const fli = @typeInfo(flt); + switch (fli) { + .@"fn" => |f| { + const args_ok = comptime args_ok: { + const f_params = f.params; + + if (f_params.len != toLuaArgs.len) break :args_ok false; + + for (0..toLuaArgs.len) |i| { + if (f_params[i].type != @TypeOf(toLuaArgs[i])) break :args_ok false; + } + + break :args_ok true; + }; + + if (args_ok) { + if (f.return_type) |rt| { + const rti = @typeInfo(rt); + switch (rti) { + .error_union => { + if (rti.error_union.payload == void) { + try @call(.auto, fl, toLuaArgs); + } else { + @compileError("toLua invalid return type, required fn signature: " ++ fnSignature); + } + }, + .void => { + @call(.auto, fl, toLuaArgs); + }, + else => { + @compileError("toLua invalid return type, required fn signature: " ++ fnSignature); + }, + } + } else { + @call(.auto, fl, toLuaArgs); + } + } else { + @compileError("toLua has invalid args, required fn signature: " ++ fnSignature); + } + }, + else => { + @compileError("toLua is not a function, required fn signature: " ++ fnSignature); + }, + } + } + } + switch (type_info) { .int, .comptime_int => { lua.pushInteger(@intCast(value)); @@ -4527,18 +4591,66 @@ pub const Lua = opaque { const type_info = @typeInfo(T); if (type_info == .@"struct" or type_info == .@"union" or type_info == .@"enum") { - if (@hasDecl(T, "ziglua_toAny")) { - const fnInfo = @typeInfo(@TypeOf(T.ziglua_toAny)).@"fn"; - switch (fnInfo.params.len) { - // fn(lua_state, alloc, allow_alloc, index) -> T - 4 => { - if (@typeInfo(fnInfo.return_type.?) == .error_union) { - return try T.ziglua_toAny(lua, a, allow_alloc, index); + if (@hasDecl(T, "fromLua")) { + const fromLuaArgs = .{ lua, a, index }; + const fnSignature = comptime fn_sign: { + var b: []const u8 = "pub fn fromLua("; + + for (0..fromLuaArgs.len) |i| { + b = b ++ std.fmt.comptimePrint("{s}{s}", .{ @typeName(@TypeOf(fromLuaArgs[i])), if (i == (fromLuaArgs.len - 1)) "" else ", " }); + } + + b = b ++ ") !" ++ @typeName(T); + + break :fn_sign b; + }; + + const fl = @field(T, "fromLua"); + const flt = @TypeOf(fl); + const fli = @typeInfo(flt); + switch (fli) { + .@"fn" => |f| { + const args_ok = comptime args_ok: { + const f_params = f.params; + + if (f_params.len != fromLuaArgs.len) break :args_ok false; + + for (0..fromLuaArgs.len) |i| { + if (f_params[i].type != @TypeOf(fromLuaArgs[i])) break :args_ok false; + } + + break :args_ok true; + }; + + if (args_ok) { + if (f.return_type) |rt| { + if (rt == T) { + return @call(.auto, fl, fromLuaArgs); + } else { + const rti = @typeInfo(rt); + switch (rti) { + .error_union => { + if (rti.error_union.payload == T) { + return try @call(.auto, fl, fromLuaArgs); + } else { + @compileError("fromLua invalid return type, required fn signature: " ++ fnSignature); + } + }, + else => { + @compileError("fromLua invalid return type, required fn signature: " ++ fnSignature); + }, + } + } + } else { + @compileError("fromLua require a fn signature: " ++ fnSignature); + } } else { - return T.ziglua_toAny(lua, a, allow_alloc, index); + @compileError("fromLua has invalid args, required fn signature: " ++ fnSignature); } }, - else => @compileError(@typeName(T) ++ ".ziglua_toAny has invalid signature, required: fn(lua: *Lua, alloc: ?std.mem.Allocator, comptime allow_alloc: bool, index: i32) T"), + else => { + @compileError("fromLua is not a function, required fn signature: " ++ fnSignature); + }, } } } diff --git a/src/tests.zig b/src/tests.zig index b0111c3..bd6598a 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -2432,7 +2432,7 @@ test "toAny tuple from struct" { )); } -test "toAny from struct with custom toAny" { +test "toAny from struct with fromLua" { var lua = try Lua.init(testing.allocator); defer lua.deinit(); @@ -2442,8 +2442,8 @@ test "toAny from struct with custom toAny" { const Self = @This(); foo: i32, - pub fn ziglua_toAny(l: *Lua, a: ?std.mem.Allocator, comptime aa: bool, i: i32) !Self { - return try ziglua.Internals.toStruct(l, Self, a, aa, i); + pub fn fromLua(l: *Lua, a: ?std.mem.Allocator, i: i32) !Self { + return try ziglua.Internals.toStruct(l, Self, a, false, i); } }, }; @@ -2460,7 +2460,6 @@ test "toAny from struct with custom toAny" { const lua_type = try lua.getGlobal("value"); try testing.expect(lua_type == .table); const my_struct = try lua.toAny(MyType, 1); - lua.pop(-1); try testing.expect(std.meta.eql( my_struct, MyType{ .foo = true, .bar = .{ .foo = 12 } }, @@ -2689,7 +2688,7 @@ test "pushAny tuple" { try testing.expect(std.meta.eql(result, .{ 500, false, 600 })); } -test "pushAny from struct with custom pushAny" { +test "pushAny from struct with toLua" { var lua = try Lua.init(testing.allocator); defer lua.deinit(); @@ -2698,7 +2697,7 @@ test "pushAny from struct with custom pushAny" { foo: i32, tuple: std.meta.Tuple(&.{ i32, i32 }), - pub fn ziglua_pushAny(self: *const Self, l: *Lua) !void { + pub fn toLua(self: Self, l: *Lua) void { l.newTable(); inline for (@typeInfo(Self).@"struct".fields) |f| { From 82f038bc611458b5c61c51846d9c2177724d9220 Mon Sep 17 00:00:00 2001 From: axdank Date: Wed, 4 Dec 2024 17:38:39 -0300 Subject: [PATCH 4/6] fix returns --- src/lib.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index 743f2f5..57a68a8 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -4429,20 +4429,20 @@ pub const Lua = opaque { switch (rti) { .error_union => { if (rti.error_union.payload == void) { - try @call(.auto, fl, toLuaArgs); + return try @call(.auto, fl, toLuaArgs); } else { @compileError("toLua invalid return type, required fn signature: " ++ fnSignature); } }, .void => { - @call(.auto, fl, toLuaArgs); + return @call(.auto, fl, toLuaArgs); }, else => { @compileError("toLua invalid return type, required fn signature: " ++ fnSignature); }, } } else { - @call(.auto, fl, toLuaArgs); + return @call(.auto, fl, toLuaArgs); } } else { @compileError("toLua has invalid args, required fn signature: " ++ fnSignature); From 5ceb75e76b27bb2df28db907c005cac846f93ac8 Mon Sep 17 00:00:00 2001 From: axdank Date: Fri, 6 Dec 2024 11:26:48 -0300 Subject: [PATCH 5/6] remove a forget block of code --- src/lib.zig | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index 57a68a8..bbe7cf9 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -4374,23 +4374,6 @@ pub const Lua = opaque { const T = @TypeOf(value); const type_info = @typeInfo(T); - if (type_info == .@"struct" or type_info == .@"union" or type_info == .@"enum") { - if (@hasDecl(T, "ziglua_pushAny")) { - const fnInfo = @typeInfo(@TypeOf(T.ziglua_pushAny)).@"fn"; - switch (fnInfo.params.len) { - // fn(self, lua) -> void - 2 => { - if (@typeInfo(fnInfo.return_type.?) == .error_union) { - return try value.ziglua_pushAny(lua); - } else { - return value.ziglua_pushAny(lua); - } - }, - else => @compileError(@typeName(T) ++ ".ziglua_pushAny has invalid signature, required: fn(self: T, lua: *Lua) void"), - } - } - } - if (type_info == .@"struct" or type_info == .@"union" or type_info == .@"enum") { if (@hasDecl(T, "toLua")) { const toLuaArgs = .{ value, lua }; From 12475b3e0908d8f7b989ed947373e6f0ceb77bd7 Mon Sep 17 00:00:00 2001 From: axdank Date: Wed, 11 Dec 2024 09:22:13 -0300 Subject: [PATCH 6/6] make public some functions --- src/lib.zig | 36 ++++-------------------------------- src/tests.zig | 2 +- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/lib.zig b/src/lib.zig index bbe7cf9..58041b2 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -585,34 +585,6 @@ pub fn Parsed(comptime T: type) type { }; } -const internals = [_][]const u8{ "toStruct", "toSlice", "toTuple", "toAnyInternal" }; - -// wrap over some internal functions of the Lua struct -pub const Internals = blk: { - const StructField = std.builtin.Type.StructField; - var fields: [internals.len]StructField = undefined; - for (internals, 0..) |entry, i| { - const F = @field(Lua, entry); - const T = @TypeOf(F); - fields[i] = .{ - .name = @ptrCast(entry), - .type = T, - .default_value = &F, - .is_comptime = false, - .alignment = @alignOf(T), - }; - } - - const TT = @Type(.{ .@"struct" = .{ - .layout = .auto, - .fields = &fields, - .decls = &.{}, - .is_tuple = false, - } }); - - break :blk TT{}; -}; - /// A Zig wrapper around the Lua C API /// Represents a Lua state or thread and contains the entire state of the Lua interpreter pub const Lua = opaque { @@ -4561,7 +4533,7 @@ pub const Lua = opaque { /// Converts the specified index of the lua stack to the specified /// type if possible and returns it /// optional allocator - fn toAnyInternal(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, index: i32) !T { + pub fn toAnyInternal(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, index: i32) !T { const stack_size_on_entry = lua.getTop(); defer { if (lua.getTop() != stack_size_on_entry) { @@ -4762,7 +4734,7 @@ pub const Lua = opaque { } /// Converts a lua array to a zig slice, memory is owned by the caller - fn toSlice(lua: *Lua, comptime ChildType: type, a: std.mem.Allocator, raw_index: i32) ![]ChildType { + pub fn toSlice(lua: *Lua, comptime ChildType: type, a: std.mem.Allocator, raw_index: i32) ![]ChildType { const index = lua.absIndex(raw_index); if (!lua.isTable(index)) { @@ -4783,7 +4755,7 @@ pub const Lua = opaque { } /// Converts value at given index to a zig struct tuple if possible - fn toTuple(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, raw_index: i32) !T { + pub fn toTuple(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, raw_index: i32) !T { const stack_size_on_entry = lua.getTop(); defer std.debug.assert(lua.getTop() == stack_size_on_entry); @@ -4826,7 +4798,7 @@ pub const Lua = opaque { } /// Converts value at given index to a zig struct if possible - fn toStruct(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, raw_index: i32) !T { + pub fn toStruct(lua: *Lua, comptime T: type, a: ?std.mem.Allocator, comptime allow_alloc: bool, raw_index: i32) !T { const stack_size_on_entry = lua.getTop(); defer std.debug.assert(lua.getTop() == stack_size_on_entry); diff --git a/src/tests.zig b/src/tests.zig index bd6598a..29352f1 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -2443,7 +2443,7 @@ test "toAny from struct with fromLua" { foo: i32, pub fn fromLua(l: *Lua, a: ?std.mem.Allocator, i: i32) !Self { - return try ziglua.Internals.toStruct(l, Self, a, false, i); + return try l.toStruct(Self, a, false, i); } }, };