2023-05-25 16:02:11 +00:00
|
|
|
const std = @import("std");
|
|
|
|
|
|
2023-06-21 14:45:14 +00:00
|
|
|
pub fn ArgsTuple(comptime funcT: anytype, comptime argsT: ?type) type {
|
|
|
|
|
const params = @typeInfo(funcT).Fn.params;
|
|
|
|
|
if (params.len == 0) {
|
|
|
|
|
return @TypeOf(.{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (@typeInfo(funcT).Fn.is_generic == false) {
|
|
|
|
|
return std.meta.ArgsTuple(funcT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const args = std.meta.fields(argsT orelse @compileError("generic function requires an explicit ArgsTuple"));
|
|
|
|
|
var tuple_fields: [params.len]std.builtin.Type.StructField = undefined;
|
|
|
|
|
inline for (params, args, 0..) |param, arg, i| {
|
|
|
|
|
if (param.type == null) {
|
|
|
|
|
tuple_fields[i] = arg;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const T = param.type.?;
|
|
|
|
|
var num_buf: [32]u8 = undefined;
|
|
|
|
|
tuple_fields[i] = .{
|
|
|
|
|
.name = blk: {
|
|
|
|
|
const s = std.fmt.formatIntBuf(&num_buf, i, 10, .lower, .{});
|
|
|
|
|
num_buf[s] = 0;
|
|
|
|
|
break :blk num_buf[0..s :0];
|
|
|
|
|
},
|
|
|
|
|
.type = T,
|
|
|
|
|
.default_value = null,
|
|
|
|
|
.is_comptime = false,
|
|
|
|
|
.alignment = if (@sizeOf(T) > 0) @alignOf(T) else 0,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return @Type(.{
|
|
|
|
|
.Struct = .{
|
|
|
|
|
.is_tuple = true,
|
|
|
|
|
.layout = .auto,
|
|
|
|
|
.decls = &.{},
|
|
|
|
|
.fields = &tuple_fields,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn TupleRange(comptime T: type, comptime start: usize, comptime end: usize) type {
|
|
|
|
|
const fields = std.meta.fields(T);
|
|
|
|
|
var new_fields: [end - start]std.builtin.Type.StructField = undefined;
|
|
|
|
|
inline for (start..end, 0..) |i, j| {
|
|
|
|
|
var new_field = fields[i];
|
|
|
|
|
var num_buf: [32]u8 = undefined;
|
|
|
|
|
new_field.name = blk: {
|
|
|
|
|
const s = std.fmt.formatIntBuf(&num_buf, j, 10, .lower, .{});
|
|
|
|
|
num_buf[s] = 0;
|
|
|
|
|
break :blk num_buf[0..s :0];
|
|
|
|
|
};
|
|
|
|
|
new_fields[j] = new_field;
|
|
|
|
|
}
|
|
|
|
|
return @Type(.{
|
|
|
|
|
.Struct = .{
|
|
|
|
|
.is_tuple = true,
|
|
|
|
|
.layout = .auto,
|
|
|
|
|
.decls = &.{},
|
|
|
|
|
.fields = &new_fields,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-25 16:02:11 +00:00
|
|
|
pub fn FnSignature(comptime func: anytype, comptime argsT: ?type) type {
|
2023-06-21 14:45:14 +00:00
|
|
|
return FnSignatureX(func, ArgsTuple(@TypeOf(func), argsT));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn FnSignatureX(comptime func: anytype, comptime argsT: type) type {
|
2023-05-25 16:02:11 +00:00
|
|
|
return struct {
|
2023-06-21 14:45:14 +00:00
|
|
|
pub const FuncT = @TypeOf(func);
|
|
|
|
|
pub const ArgsT = argsT;
|
2023-05-25 16:02:11 +00:00
|
|
|
pub const ReturnT = @TypeOf(@call(.auto, func, @as(ArgsT, undefined)));
|
2023-06-21 14:45:14 +00:00
|
|
|
pub const ReturnPayloadT = switch (@typeInfo(ReturnT)) {
|
|
|
|
|
.ErrorUnion => |u| u.payload,
|
|
|
|
|
else => ReturnT,
|
2023-05-25 16:02:11 +00:00
|
|
|
};
|
2023-06-21 14:45:14 +00:00
|
|
|
pub const ReturnErrorSet: ?type = switch (@typeInfo(ReturnT)) {
|
|
|
|
|
.ErrorUnion => |u| u.error_set,
|
|
|
|
|
else => null,
|
2023-05-25 16:02:11 +00:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|