Skip to content

Commit 31d1abd

Browse files
authored
Merge pull request #177 from natecraddock/push-pqvzpxwmlnuz
fix: avoid std.meta.Tuple
2 parents fd89bfa + 3b7c3c4 commit 31d1abd

File tree

1 file changed

+144
-168
lines changed

1 file changed

+144
-168
lines changed

src/lib.zig

Lines changed: 144 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,7 @@ pub const Stream = c.luaL_Stream;
562562
pub const Unsigned = c.lua_Unsigned;
563563

564564
/// The type of warning functions used by Lua to emit warnings
565-
pub const CWarnFn = switch (lang) {
566-
.lua54 => *const fn (data: ?*anyopaque, msg: [*c]const u8, to_cont: c_int) callconv(.c) void,
567-
else => @compileError("CWarnFn not defined"),
568-
};
565+
pub const CWarnFn = *const fn (data: ?*anyopaque, msg: [*c]const u8, to_cont: c_int) callconv(.c) void;
569566

570567
/// The type of the writer function used by `Lua.dump()`
571568
pub const CWriterFn = *const fn (state: ?*LuaState, buf: ?*const anyopaque, size: usize, data: ?*anyopaque) callconv(.c) c_int;
@@ -5157,21 +5154,30 @@ pub const Buffer = struct {
51575154

51585155
// Helper functions to make the zlua API easier to use
51595156

5160-
const Tuple = std.meta.Tuple;
5161-
51625157
fn TypeOfWrap(comptime function: anytype) type {
5163-
const Args = std.meta.ArgsTuple(@TypeOf(function));
5164-
return switch (Args) {
5165-
Tuple(&.{*Lua}) => CFn,
5166-
Tuple(&.{ *Lua, Event, *DebugInfo }) => CHookFn,
5167-
Tuple(&.{ *Lua, Status, Context }) => CContFn,
5168-
Tuple(&.{ *Lua, *anyopaque }) => CReaderFn,
5169-
Tuple(&.{*anyopaque}) => CUserdataDtorFn,
5170-
Tuple(&.{ *Lua, i32 }) => CInterruptCallbackFn,
5171-
Tuple(&.{[]const u8}) => CUserAtomCallbackFn,
5172-
Tuple(&.{ ?*anyopaque, []const u8, bool }) => CWarnFn,
5173-
Tuple(&.{ *Lua, []const u8, *anyopaque }) => CWriterFn,
5174-
else => @compileError("Unsupported function given to wrap '" ++ @typeName(@TypeOf(function)) ++ "'"),
5158+
const params = @typeInfo(@TypeOf(function)).@"fn".params;
5159+
if (params.len == 1) {
5160+
if (params[0].type.? == *Lua) return CFn;
5161+
if (params[0].type.? == []const u8) return CUserAtomCallbackFn;
5162+
if (params[0].type.? == *anyopaque) return CUserdataDtorFn;
5163+
}
5164+
if (params.len == 2) {
5165+
if (params[0].type.? == *Lua) {
5166+
if (params[1].type.? == i32) return CInterruptCallbackFn;
5167+
if (params[1].type.? == *anyopaque) return CReaderFn;
5168+
}
5169+
}
5170+
if (params.len == 3) {
5171+
if (params[0].type.? == ?*anyopaque and params[1].type.? == []const u8 and params[2].type.? == bool) return CWarnFn;
5172+
if (params[0].type.? == *Lua) {
5173+
if (params[1].type.? == Event and params[2].type.? == *DebugInfo) return CHookFn;
5174+
if (params[1].type.? == Status and params[2].type.? == Context) return CContFn;
5175+
if (params[1].type.? == []const u8 and params[2].type.? == *anyopaque) return CWriterFn;
5176+
}
5177+
}
5178+
return {
5179+
@compileLog(@TypeOf(function));
5180+
@compileError("Unsupported function given to wrap.");
51755181
};
51765182
}
51775183

@@ -5190,169 +5196,139 @@ fn TypeOfWrap(comptime function: anytype) type {
51905196
/// Functions that accept a `*Lua` pointer also support returning error unions. For example,
51915197
/// wrap also supports `fn (lua: *Lua) !i32` for a `CFn`.
51925198
pub fn wrap(comptime function: anytype) TypeOfWrap(function) {
5193-
const info = @typeInfo(@TypeOf(function));
5194-
if (info != .@"fn") {
5195-
@compileError("Wrap only accepts functions");
5196-
}
5197-
5198-
const has_error_union = @typeInfo(info.@"fn".return_type.?) == .error_union;
5199-
5200-
const Args = std.meta.ArgsTuple(@TypeOf(function));
5201-
switch (Args) {
5202-
// CFn
5203-
Tuple(&.{*Lua}) => {
5204-
return struct {
5205-
fn inner(state: ?*LuaState) callconv(.c) c_int {
5206-
// this is called by Lua, state should never be null
5207-
var lua: *Lua = @ptrCast(state.?);
5208-
if (has_error_union) {
5209-
return @call(.always_inline, function, .{lua}) catch |err| {
5210-
lua.raiseErrorStr(@errorName(err), .{});
5211-
};
5212-
} else {
5213-
return @call(.always_inline, function, .{lua});
5214-
}
5199+
const info = @typeInfo(@TypeOf(function)).@"fn";
5200+
5201+
const has_error_union = @typeInfo(info.return_type.?) == .error_union;
5202+
5203+
const Return = TypeOfWrap(function);
5204+
return switch (Return) {
5205+
CFn => struct {
5206+
fn inner(state: ?*LuaState) callconv(.c) c_int {
5207+
// this is called by Lua, state should never be null
5208+
var lua: *Lua = @ptrCast(state.?);
5209+
if (has_error_union) {
5210+
return @call(.always_inline, function, .{lua}) catch |err| {
5211+
lua.raiseErrorStr(@errorName(err), .{});
5212+
};
5213+
} else {
5214+
return @call(.always_inline, function, .{lua});
52155215
}
5216-
}.inner;
5217-
},
5218-
// CHookFn
5219-
Tuple(&.{ *Lua, Event, *DebugInfo }) => {
5220-
return struct {
5221-
fn inner(state: ?*LuaState, ar: ?*Debug) callconv(.c) void {
5222-
// this is called by Lua, state should never be null
5223-
var lua: *Lua = @ptrCast(state.?);
5224-
var debug_info: DebugInfo = .{
5225-
.current_line = if (ar.?.currentline == -1) null else ar.?.currentline,
5226-
.private = switch (lang) {
5227-
.lua51, .luajit => ar.?.i_ci,
5228-
else => @ptrCast(ar.?.i_ci),
5229-
},
5216+
}
5217+
}.inner,
5218+
CHookFn => struct {
5219+
fn inner(state: ?*LuaState, ar: ?*Debug) callconv(.c) void {
5220+
// this is called by Lua, state should never be null
5221+
var lua: *Lua = @ptrCast(state.?);
5222+
var debug_info: DebugInfo = .{
5223+
.current_line = if (ar.?.currentline == -1) null else ar.?.currentline,
5224+
.private = switch (lang) {
5225+
.lua51, .luajit => ar.?.i_ci,
5226+
else => @ptrCast(ar.?.i_ci),
5227+
},
5228+
};
5229+
if (has_error_union) {
5230+
@call(.always_inline, function, .{ lua, @as(Event, @enumFromInt(ar.?.event)), &debug_info }) catch |err| {
5231+
lua.raiseErrorStr(@errorName(err), .{});
52305232
};
5231-
if (has_error_union) {
5232-
@call(.always_inline, function, .{ lua, @as(Event, @enumFromInt(ar.?.event)), &debug_info }) catch |err| {
5233-
lua.raiseErrorStr(@errorName(err), .{});
5234-
};
5235-
} else {
5236-
@call(.always_inline, function, .{ lua, @as(Event, @enumFromInt(ar.?.event)), &debug_info });
5237-
}
5233+
} else {
5234+
@call(.always_inline, function, .{ lua, @as(Event, @enumFromInt(ar.?.event)), &debug_info });
52385235
}
5239-
}.inner;
5240-
},
5241-
// CContFn
5242-
Tuple(&.{ *Lua, Status, Context }) => {
5243-
return struct {
5244-
fn inner(state: ?*LuaState, status: c_int, ctx: Context) callconv(.c) c_int {
5245-
// this is called by Lua, state should never be null
5246-
var lua: *Lua = @ptrCast(state.?);
5247-
if (has_error_union) {
5248-
return @call(.always_inline, function, .{ lua, @as(Status, @enumFromInt(status)), ctx }) catch |err| {
5249-
lua.raiseErrorStr(@errorName(err), .{});
5250-
};
5251-
} else {
5252-
return @call(.always_inline, function, .{ lua, @as(Status, @enumFromInt(status)), ctx });
5253-
}
5236+
}
5237+
}.inner,
5238+
CContFn => struct {
5239+
fn inner(state: ?*LuaState, status: c_int, ctx: Context) callconv(.c) c_int {
5240+
// this is called by Lua, state should never be null
5241+
var lua: *Lua = @ptrCast(state.?);
5242+
if (has_error_union) {
5243+
return @call(.always_inline, function, .{ lua, @as(Status, @enumFromInt(status)), ctx }) catch |err| {
5244+
lua.raiseErrorStr(@errorName(err), .{});
5245+
};
5246+
} else {
5247+
return @call(.always_inline, function, .{ lua, @as(Status, @enumFromInt(status)), ctx });
52545248
}
5255-
}.inner;
5256-
},
5257-
// CReaderFn
5258-
Tuple(&.{ *Lua, *anyopaque }) => {
5259-
return struct {
5260-
fn inner(state: ?*LuaState, data: ?*anyopaque, size: [*c]usize) callconv(.c) [*c]const u8 {
5261-
// this is called by Lua, state should never be null
5262-
var lua: *Lua = @ptrCast(state.?);
5263-
if (has_error_union) {
5264-
const result = @call(.always_inline, function, .{ lua, data.? }) catch |err| {
5265-
lua.raiseErrorStr(@errorName(err), .{});
5266-
};
5267-
if (result) |buffer| {
5268-
size.* = buffer.len;
5269-
return buffer.ptr;
5270-
} else {
5271-
size.* = 0;
5272-
return null;
5273-
}
5249+
}
5250+
}.inner,
5251+
CReaderFn => struct {
5252+
fn inner(state: ?*LuaState, data: ?*anyopaque, size: [*c]usize) callconv(.c) [*c]const u8 {
5253+
// this is called by Lua, state should never be null
5254+
var lua: *Lua = @ptrCast(state.?);
5255+
if (has_error_union) {
5256+
const result = @call(.always_inline, function, .{ lua, data.? }) catch |err| {
5257+
lua.raiseErrorStr(@errorName(err), .{});
5258+
};
5259+
if (result) |buffer| {
5260+
size.* = buffer.len;
5261+
return buffer.ptr;
52745262
} else {
5275-
if (@call(.always_inline, function, .{ lua, data.? })) |buffer| {
5276-
size.* = buffer.len;
5277-
return buffer.ptr;
5278-
} else {
5279-
size.* = 0;
5280-
return null;
5281-
}
5263+
size.* = 0;
5264+
return null;
52825265
}
5283-
}
5284-
}.inner;
5285-
},
5286-
// CUserdataDtorFn
5287-
Tuple(&.{*anyopaque}) => {
5288-
return struct {
5289-
fn inner(userdata: *anyopaque) callconv(.c) void {
5290-
return @call(.always_inline, function, .{userdata});
5291-
}
5292-
}.inner;
5293-
},
5294-
// CInterruptCallbackFn
5295-
Tuple(&.{ *Lua, i32 }) => {
5296-
return struct {
5297-
fn inner(state: ?*LuaState, gc: c_int) callconv(.c) void {
5298-
// this is called by Lua, state should never be null
5299-
var lua: *Lua = @ptrCast(state.?);
5300-
if (has_error_union) {
5301-
@call(.always_inline, function, .{ lua, gc }) catch |err| {
5302-
lua.raiseErrorStr(@errorName(err), .{});
5303-
};
5266+
} else {
5267+
if (@call(.always_inline, function, .{ lua, data.? })) |buffer| {
5268+
size.* = buffer.len;
5269+
return buffer.ptr;
53045270
} else {
5305-
@call(.always_inline, function, .{ lua, gc });
5271+
size.* = 0;
5272+
return null;
53065273
}
53075274
}
5308-
}.inner;
5309-
},
5310-
// CUserAtomCallbackFn
5311-
Tuple(&.{[]const u8}) => {
5312-
return struct {
5313-
fn inner(str: [*c]const u8, len: usize) callconv(.c) i16 {
5314-
if (str) |s| {
5315-
const buf = s[0..len];
5316-
return @call(.always_inline, function, .{buf});
5317-
}
5318-
return -1;
5275+
}
5276+
}.inner,
5277+
CUserdataDtorFn => struct {
5278+
fn inner(userdata: *anyopaque) callconv(.c) void {
5279+
return @call(.always_inline, function, .{userdata});
5280+
}
5281+
}.inner,
5282+
CInterruptCallbackFn => struct {
5283+
fn inner(state: ?*LuaState, gc: c_int) callconv(.c) void {
5284+
// this is called by Lua, state should never be null
5285+
var lua: *Lua = @ptrCast(state.?);
5286+
if (has_error_union) {
5287+
@call(.always_inline, function, .{ lua, gc }) catch |err| {
5288+
lua.raiseErrorStr(@errorName(err), .{});
5289+
};
5290+
} else {
5291+
@call(.always_inline, function, .{ lua, gc });
53195292
}
5320-
}.inner;
5321-
},
5322-
// CWarnFn
5323-
Tuple(&.{ ?*anyopaque, []const u8, bool }) => {
5324-
return struct {
5325-
fn inner(data: ?*anyopaque, msg: [*c]const u8, to_cont: c_int) callconv(.c) void {
5326-
// warning messages emitted from Lua should be null-terminated for display
5327-
const message = std.mem.span(@as([*:0]const u8, @ptrCast(msg)));
5328-
@call(.always_inline, function, .{ data, message, to_cont != 0 });
5293+
}
5294+
}.inner,
5295+
CUserAtomCallbackFn => struct {
5296+
fn inner(str: [*c]const u8, len: usize) callconv(.c) i16 {
5297+
if (str) |s| {
5298+
const buf = s[0..len];
5299+
return @call(.always_inline, function, .{buf});
53295300
}
5330-
}.inner;
5331-
},
5332-
// CWriterFn
5333-
Tuple(&.{ *Lua, []const u8, *anyopaque }) => {
5334-
return struct {
5335-
fn inner(state: ?*LuaState, buf: ?*const anyopaque, size: usize, data: ?*anyopaque) callconv(.c) c_int {
5336-
// this is called by Lua, state should never be null
5337-
var lua: *Lua = @ptrCast(state.?);
5338-
const buffer = @as([*]const u8, @ptrCast(buf))[0..size];
5339-
5340-
const result = if (has_error_union) blk: {
5341-
break :blk @call(.always_inline, function, .{ lua, buffer, data.? }) catch |err| {
5342-
lua.raiseErrorStr(@errorName(err), .{});
5343-
};
5344-
} else blk: {
5345-
break :blk @call(.always_inline, function, .{ lua, buffer, data.? });
5301+
return -1;
5302+
}
5303+
}.inner,
5304+
CWarnFn => if (lang != .lua54) @compileError("CWarnFn is only valid in Lua >= 5.4") else struct {
5305+
fn inner(data: ?*anyopaque, msg: [*c]const u8, to_cont: c_int) callconv(.c) void {
5306+
// warning messages emitted from Lua should be null-terminated for display
5307+
const message = std.mem.span(@as([*:0]const u8, @ptrCast(msg)));
5308+
@call(.always_inline, function, .{ data, message, to_cont != 0 });
5309+
}
5310+
}.inner,
5311+
CWriterFn => struct {
5312+
fn inner(state: ?*LuaState, buf: ?*const anyopaque, size: usize, data: ?*anyopaque) callconv(.c) c_int {
5313+
// this is called by Lua, state should never be null
5314+
var lua: *Lua = @ptrCast(state.?);
5315+
const buffer = @as([*]const u8, @ptrCast(buf))[0..size];
5316+
5317+
const result = if (has_error_union) blk: {
5318+
break :blk @call(.always_inline, function, .{ lua, buffer, data.? }) catch |err| {
5319+
lua.raiseErrorStr(@errorName(err), .{});
53465320
};
5321+
} else blk: {
5322+
break :blk @call(.always_inline, function, .{ lua, buffer, data.? });
5323+
};
53475324

5348-
// it makes more sense for the inner writer function to return false for failure,
5349-
// so negate the result here
5350-
return @intFromBool(!result);
5351-
}
5352-
}.inner;
5353-
},
5354-
else => @compileError("Unsupported function given to wrap '" ++ @typeName(@TypeOf(function)) ++ "'"),
5355-
}
5325+
// it makes more sense for the inner writer function to return false for failure,
5326+
// so negate the result here
5327+
return @intFromBool(!result);
5328+
}
5329+
}.inner,
5330+
else => unreachable,
5331+
};
53565332
}
53575333

53585334
/// Zig wrapper for Luau lua_CompileOptions that uses the same defaults as Luau if

0 commit comments

Comments
 (0)