Last active
September 2, 2023 00:18
-
-
Save tauoverpi/360f32c98b8061f2ab884517218245d7 to your computer and use it in GitHub Desktop.
Comptime is a trap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub fn dispatch(arena: Allocator, cwd: Dir, context: Context, argv: []const [*:0]const u8, comptime hooks: Self) !void { | |
const basename = fs.path.basename(mem.span(argv[0])); | |
const command = Self.map.get(basename) orelse return error.UnknownCommand; | |
switch (command) { | |
inline else => |tag| { | |
const com = @field(hooks, @tagName(tag)); | |
const Fn = @TypeOf(com); | |
const info = @typeInfo(Fn).Fn; | |
var tuple: meta.ArgsTuple(Fn) = undefined; | |
tuple[0] = arena; | |
tuple[1] = context; | |
var range: usize = 0; | |
defer inline for (info.params[2..], 2..) |param, index| { | |
switch (param.type.?) { | |
File => if (index < range) tuple[index].close(), | |
else => {}, | |
} | |
}; | |
inline for (info.params[2..], 1..) |param, index| { | |
range += 1; | |
const T = param.type.?; | |
if (@typeInfo(T) != .Optional and index >= argv.len) { | |
return error.TooFewArgs; | |
} | |
const value = switch (@typeInfo(T)) { | |
.Int => try std.fmt.parseInt(T, mem.span(argv[index]), 10), | |
.Optional => |opt| if (index < argv.len) switch (opt.child) { | |
Self.Source => blk: { | |
const source = std.meta.stringToEnum(Self.Source.Tag, mem.span(argv[index])) orelse | |
return error.InvalidSource; | |
break :blk switch (source) { | |
.commit => if (index + 1 >= argv.len) | |
return error.MissingArgument | |
else | |
@as(Self.Source, .{ .commit = mem.span(argv[index + 1]) }), | |
inline else => |name| @unionInit(Self.Source, @tagName(name), {}), | |
}; | |
}, | |
[]const u8 => mem.span(argv[index]), | |
else => @compileError(@typeName(T) ++ " is not supported for optional arguments"), | |
} else null, | |
else => switch (T) { | |
File => try cwd.openFile(mem.span(argv[index]), .{ .mode = .read_write }), | |
Self.Command => meta.stringToEnum(Self.Command, mem.span(argv[index])) orelse return error.InvalidCommand, | |
Self.Status => meta.stringToEnum(Self.Status, mem.span(argv[index])) orelse return error.InvalidStatus, | |
Self.State => meta.stringToEnum(Self.State, mem.span(argv[index])) orelse return error.InvalidState, | |
Self.Type => meta.stringToEnum(Self.Type, mem.span(argv[index])) orelse return error.InvalidType, | |
[]const u8 => mem.span(argv[index]), | |
[]const [*:0]const u8 => argv[1..], | |
else => @compileError(@typeName(T) ++ " is not supported for regular arguments"), | |
}, | |
}; | |
tuple[index + 1] = value; | |
} | |
try @call(.auto, com, tuple); | |
}, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment