diff --git a/src/bunfig.zig b/src/bunfig.zig index 39cf0d3b7e..f6c115a398 100644 --- a/src/bunfig.zig +++ b/src/bunfig.zig @@ -108,17 +108,17 @@ pub const Bunfig = struct { fn loadLogLevel(this: *Parser, expr: js_ast.Expr) !void { try this.expectString(expr); - const Matcher = strings.ExactSizeMatcher(8); + const LogLevelMap = bun.ComptimeStringMap(api.MessageLevel, .{ + .{ "debug", api.MessageLevel.debug }, + .{ "error", api.MessageLevel.err }, + .{ "warn", api.MessageLevel.warn }, + .{ "info", api.MessageLevel.info }, + }); - this.bunfig.log_level = switch (Matcher.match(expr.asString(this.allocator).?)) { - Matcher.case("debug") => api.MessageLevel.debug, - Matcher.case("error") => api.MessageLevel.err, - Matcher.case("warn") => api.MessageLevel.warn, - Matcher.case("info") => api.MessageLevel.info, - else => { - try this.addError(expr.loc, "Invalid log level, must be one of debug, error, or warn"); - unreachable; - }, + const log_str = expr.asString(this.allocator).?; + this.bunfig.log_level = LogLevelMap.get(log_str) orelse { + try this.addError(expr.loc, "Invalid log level, must be one of debug, error, or warn"); + unreachable; }; } diff --git a/src/cli.zig b/src/cli.zig index ea1129320e..7d56d255d9 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -539,79 +539,67 @@ pub const Command = struct { } const first_arg_name = next_arg; - const RootCommandMatcher = strings.ExactSizeMatcher(12); - - return switch (RootCommandMatcher.match(first_arg_name)) { - RootCommandMatcher.case("init") => .InitCommand, - RootCommandMatcher.case("build"), RootCommandMatcher.case("bun") => .BuildCommand, - RootCommandMatcher.case("discord") => .DiscordCommand, - RootCommandMatcher.case("upgrade") => .UpgradeCommand, - RootCommandMatcher.case("completions") => .InstallCompletionsCommand, - RootCommandMatcher.case("getcompletes") => .GetCompletionsCommand, - RootCommandMatcher.case("link") => .LinkCommand, - RootCommandMatcher.case("unlink") => .UnlinkCommand, - RootCommandMatcher.case("x") => .BunxCommand, - RootCommandMatcher.case("repl") => .ReplCommand, - - RootCommandMatcher.case("i"), - RootCommandMatcher.case("install"), - => brk: { - for (args_iter.buf) |arg| { - if (arg.len > 0 and (strings.eqlComptime(arg, "-g") or strings.eqlComptime(arg, "--global"))) { - break :brk .AddCommand; - } - } - - break :brk .InstallCommand; - }, - RootCommandMatcher.case("ci") => .InstallCommand, - RootCommandMatcher.case("c"), RootCommandMatcher.case("create") => .CreateCommand, - - RootCommandMatcher.case("test") => .TestCommand, - - RootCommandMatcher.case("pm") => .PackageManagerCommand, - - RootCommandMatcher.case("add"), RootCommandMatcher.case("a") => .AddCommand, - - RootCommandMatcher.case("update") => .UpdateCommand, - RootCommandMatcher.case("patch") => .PatchCommand, - RootCommandMatcher.case("patch-commit") => .PatchCommitCommand, - - RootCommandMatcher.case("r"), - RootCommandMatcher.case("remove"), - RootCommandMatcher.case("rm"), - RootCommandMatcher.case("uninstall"), - => .RemoveCommand, - - RootCommandMatcher.case("run") => .RunCommand, - RootCommandMatcher.case("help") => .HelpCommand, - - RootCommandMatcher.case("exec") => .ExecCommand, - - RootCommandMatcher.case("outdated") => .OutdatedCommand, - RootCommandMatcher.case("publish") => .PublishCommand, - RootCommandMatcher.case("audit") => .AuditCommand, - RootCommandMatcher.case("info") => .InfoCommand, - + const RootCommandMap = bun.ComptimeStringMap(Command.Tag, .{ + .{ "init", .InitCommand }, + .{ "build", .BuildCommand }, + .{ "bun", .BuildCommand }, + .{ "discord", .DiscordCommand }, + .{ "upgrade", .UpgradeCommand }, + .{ "completions", .InstallCompletionsCommand }, + .{ "getcompletes", .GetCompletionsCommand }, + .{ "link", .LinkCommand }, + .{ "unlink", .UnlinkCommand }, + .{ "x", .BunxCommand }, + .{ "repl", .ReplCommand }, + .{ "ci", .InstallCommand }, + .{ "c", .CreateCommand }, + .{ "create", .CreateCommand }, + .{ "test", .TestCommand }, + .{ "pm", .PackageManagerCommand }, + .{ "add", .AddCommand }, + .{ "a", .AddCommand }, + .{ "update", .UpdateCommand }, + .{ "patch", .PatchCommand }, + .{ "patch-commit", .PatchCommitCommand }, + .{ "r", .RemoveCommand }, + .{ "remove", .RemoveCommand }, + .{ "rm", .RemoveCommand }, + .{ "uninstall", .RemoveCommand }, + .{ "run", .RunCommand }, + .{ "help", .HelpCommand }, + .{ "exec", .ExecCommand }, + .{ "outdated", .OutdatedCommand }, + .{ "publish", .PublishCommand }, + .{ "audit", .AuditCommand }, + .{ "info", .InfoCommand }, // These are reserved for future use by Bun, so that someone // doing `bun deploy` to run a script doesn't accidentally break // when we add our actual command - RootCommandMatcher.case("deploy") => .ReservedCommand, - RootCommandMatcher.case("cloud") => .ReservedCommand, - RootCommandMatcher.case("config") => .ReservedCommand, - RootCommandMatcher.case("use") => .ReservedCommand, - RootCommandMatcher.case("auth") => .ReservedCommand, - RootCommandMatcher.case("login") => .ReservedCommand, - RootCommandMatcher.case("logout") => .ReservedCommand, - RootCommandMatcher.case("whoami") => .PackageManagerCommand, - RootCommandMatcher.case("prune") => .ReservedCommand, - RootCommandMatcher.case("list") => .ReservedCommand, - RootCommandMatcher.case("why") => .WhyCommand, + .{ "deploy", .ReservedCommand }, + .{ "cloud", .ReservedCommand }, + .{ "config", .ReservedCommand }, + .{ "use", .ReservedCommand }, + .{ "auth", .ReservedCommand }, + .{ "login", .ReservedCommand }, + .{ "logout", .ReservedCommand }, + .{ "whoami", .PackageManagerCommand }, + .{ "prune", .ReservedCommand }, + .{ "list", .ReservedCommand }, + .{ "why", .WhyCommand }, + .{ "-e", .AutoCommand }, + }); - RootCommandMatcher.case("-e") => .AutoCommand, + // Special case for install/i commands needing to check for global flag + if (strings.eql(first_arg_name, "install") or strings.eql(first_arg_name, "i")) { + for (args_iter.buf) |arg| { + if (arg.len > 0 and (strings.eqlComptime(arg, "-g") or strings.eqlComptime(arg, "--global"))) { + return .AddCommand; + } + } + return .InstallCommand; + } - else => .AutoCommand, - }; + return RootCommandMap.get(first_arg_name) orelse .AutoCommand; } const default_completions_list = [_]string{ diff --git a/src/cli/Arguments.zig b/src/cli/Arguments.zig index f0884f20df..dcc8f7d56f 100644 --- a/src/cli/Arguments.zig +++ b/src/cli/Arguments.zig @@ -876,7 +876,12 @@ pub fn parse(allocator: std.mem.Allocator, ctx: Command.Context, comptime cmd: C } } - const TargetMatcher = strings.ExactSizeMatcher(8); + const TargetMap = bun.ComptimeStringMap(Api.Target, .{ + .{ "browser", Api.Target.browser }, + .{ "node", Api.Target.node }, + .{ "macro", if (cmd == .BuildCommand) Api.Target.bun_macro else Api.Target.bun }, + .{ "bun", Api.Target.bun }, + }); if (args.option("--target")) |_target| brk: { if (comptime cmd == .BuildCommand) { if (args.flag("--compile")) { @@ -892,13 +897,7 @@ pub fn parse(allocator: std.mem.Allocator, ctx: Command.Context, comptime cmd: C } } - opts.target = opts.target orelse switch (TargetMatcher.match(_target)) { - TargetMatcher.case("browser") => Api.Target.browser, - TargetMatcher.case("node") => Api.Target.node, - TargetMatcher.case("macro") => if (cmd == .BuildCommand) Api.Target.bun_macro else Api.Target.bun, - TargetMatcher.case("bun") => Api.Target.bun, - else => CLI.invalidTarget(&diag, _target), - }; + opts.target = opts.target orelse TargetMap.get(_target) orelse CLI.invalidTarget(&diag, _target); if (opts.target.? == .bun) { ctx.debug.run_in_bun = opts.target.? == .bun; diff --git a/src/install/integrity.zig b/src/install/integrity.zig index e2ad24789f..efc1cb3ab0 100644 --- a/src/install/integrity.zig +++ b/src/install/integrity.zig @@ -125,7 +125,12 @@ pub const Integrity = extern struct { } pub fn parse(buf: []const u8) struct { Tag, usize } { - const Matcher = strings.ExactSizeMatcher(8); + const TagMap = bun.ComptimeStringMap(Tag, .{ + .{ "sha1", Tag.sha1 }, + .{ "sha256", Tag.sha256 }, + .{ "sha384", Tag.sha384 }, + .{ "sha512", Tag.sha512 }, + }); const i = strings.indexOfChar(buf[0..@min(buf.len, 7)], '-') orelse return .{ Tag.unknown, 0 }; @@ -133,13 +138,11 @@ pub const Integrity = extern struct { return .{ Tag.unknown, 0 }; } - return switch (Matcher.match(buf[0..i])) { - Matcher.case("sha1") => .{ Tag.sha1, i + 1 }, - Matcher.case("sha256") => .{ Tag.sha256, i + 1 }, - Matcher.case("sha384") => .{ Tag.sha384, i + 1 }, - Matcher.case("sha512") => .{ Tag.sha512, i + 1 }, - else => .{ Tag.unknown, 0 }, - }; + const tag = TagMap.get(buf[0..i]) orelse Tag.unknown; + if (tag == Tag.unknown) { + return .{ Tag.unknown, 0 }; + } + return .{ tag, i + 1 }; } pub inline fn digestLen(this: Tag) usize { diff --git a/src/string/immutable.zig b/src/string/immutable.zig index b478beb491..3774367169 100644 --- a/src/string/immutable.zig +++ b/src/string/immutable.zig @@ -1928,8 +1928,6 @@ pub fn moveSlice(slice: string, from: string, to: string) string { return result; } -pub const ExactSizeMatcher = @import("./immutable/exact_size_matcher.zig").ExactSizeMatcher; - pub const unicode_replacement = 0xFFFD; pub const unicode_replacement_str = brk: { var out: [std.unicode.utf8CodepointSequenceLength(unicode_replacement) catch unreachable]u8 = undefined; diff --git a/src/string/immutable/exact_size_matcher.zig b/src/string/immutable/exact_size_matcher.zig deleted file mode 100644 index acd702a750..0000000000 --- a/src/string/immutable/exact_size_matcher.zig +++ /dev/null @@ -1,72 +0,0 @@ -pub fn ExactSizeMatcher(comptime max_bytes: usize) type { - switch (max_bytes) { - 1, 2, 4, 8, 12, 16 => {}, - else => { - @compileError("max_bytes must be 1, 2, 4, 8, 12, or 16."); - }, - } - - const T = std.meta.Int( - .unsigned, - max_bytes * 8, - ); - - return struct { - pub fn match(str: anytype) T { - switch (str.len) { - 1...max_bytes - 1 => { - var tmp: [max_bytes]u8 = undefined; - @memcpy(tmp[0..str.len], str); - @memset(tmp[str.len..], 0); - - return std.mem.readInt(T, &tmp, .little); - }, - max_bytes => { - return std.mem.readInt(T, str[0..max_bytes], .little); - }, - 0 => { - return 0; - }, - else => { - return std.math.maxInt(T); - }, - } - } - - pub fn matchLower(str: anytype) T { - switch (str.len) { - 1...max_bytes - 1 => { - var tmp: [max_bytes]u8 = undefined; - for (str, 0..) |char, i| { - tmp[i] = std.ascii.toLower(char); - } - @memset(tmp[str.len..], 0); - return std.mem.readInt(T, &tmp, .little); - }, - max_bytes => { - return std.mem.readInt(T, str[0..max_bytes], .little); - }, - 0 => { - return 0; - }, - else => { - return std.math.maxInt(T); - }, - } - } - - pub fn case(comptime str: []const u8) T { - if (str.len < max_bytes) { - var bytes = std.mem.zeroes([max_bytes]u8); - bytes[0..str.len].* = str[0..str.len].*; - return std.mem.readInt(T, &bytes, .little); - } else if (str.len == max_bytes) { - return std.mem.readInt(T, str[0..str.len], .little); - } else { - @compileError("str: \"" ++ str ++ "\" too long"); - } - } - }; -} - -const std = @import("std");