lib/tracy/src/cli/args/find.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const tracy = @import("../../root.zig");
  3 const scalar = @import("scalar.zig");
  4 const types = @import("types.zig");
  5 
  6 pub fn parse(args: []const []const u8) !types.FindArgs {
  7     if (args.len < 2) return error.InvalidArguments;
  8     var parsed = types.FindArgs{
  9         .path = args[0],
 10         .options = .{ .pattern = args[1] },
 11     };
 12     var around_ns: ?u64 = null;
 13     var window_ns: ?u64 = null;
 14     var index: usize = 2;
 15     while (index < args.len) : (index += 1) {
 16         if (std.mem.eql(u8, args[index], "--format")) {
 17             index += 1;
 18             if (index >= args.len) return error.InvalidArguments;
 19             if (std.mem.eql(u8, args[index], "text")) {
 20                 parsed.format = .text;
 21             } else if (std.mem.eql(u8, args[index], "jsonl")) {
 22                 parsed.format = .jsonl;
 23             } else {
 24                 return error.UnsupportedFormat;
 25             }
 26         } else if (std.mem.eql(u8, args[index], "--top")) {
 27             index += 1;
 28             if (index >= args.len) return error.InvalidArguments;
 29             parsed.options.top = try scalar.parsePositiveUsize(args[index]);
 30         } else if (std.mem.eql(u8, args[index], "--occurrences")) {
 31             index += 1;
 32             if (index >= args.len) return error.InvalidArguments;
 33             parsed.options.occurrences = try scalar.parseUsize(args[index]);
 34         } else if (std.mem.eql(u8, args[index], "--group")) {
 35             index += 1;
 36             if (index >= args.len) return error.InvalidArguments;
 37             parsed.options.group = tracy.find.Group.fromName(args[index]) orelse return error.UnsupportedGroup;
 38         } else if (std.mem.eql(u8, args[index], "--sort")) {
 39             index += 1;
 40             if (index >= args.len) return error.InvalidArguments;
 41             parsed.options.sort = tracy.find.Sort.fromName(args[index]) orelse return error.UnsupportedSort;
 42         } else if (std.mem.eql(u8, args[index], "--thread")) {
 43             index += 1;
 44             if (index >= args.len) return error.InvalidArguments;
 45             parsed.options.thread = try scalar.parseU64(args[index]);
 46         } else if (std.mem.eql(u8, args[index], "--since-ns")) {
 47             index += 1;
 48             if (index >= args.len) return error.InvalidArguments;
 49             parsed.options.since_ns = try scalar.parseU64(args[index]);
 50         } else if (std.mem.eql(u8, args[index], "--until-ns")) {
 51             index += 1;
 52             if (index >= args.len) return error.InvalidArguments;
 53             parsed.options.until_ns = try scalar.parseU64(args[index]);
 54         } else if (std.mem.eql(u8, args[index], "--around-ns")) {
 55             index += 1;
 56             if (index >= args.len) return error.InvalidArguments;
 57             around_ns = try scalar.parseU64(args[index]);
 58         } else if (std.mem.eql(u8, args[index], "--window-ns")) {
 59             index += 1;
 60             if (index >= args.len) return error.InvalidArguments;
 61             window_ns = try scalar.parseU64(args[index]);
 62         } else if (std.mem.eql(u8, args[index], "--min-duration-ns")) {
 63             index += 1;
 64             if (index >= args.len) return error.InvalidArguments;
 65             parsed.options.min_duration_ns = try scalar.parseU64(args[index]);
 66         } else if (std.mem.eql(u8, args[index], "--ignore-case")) {
 67             parsed.options.ignore_case = true;
 68         } else {
 69             return error.UnknownArgument;
 70         }
 71     }
 72     if (around_ns) |center| {
 73         if (parsed.options.since_ns != null or parsed.options.until_ns != null) return error.InvalidArguments;
 74         const width = window_ns orelse 1_000_000;
 75         const half = width / 2;
 76         parsed.options.since_ns = if (center > half) center - half else 0;
 77         parsed.options.until_ns = center +| (width - half);
 78     } else if (window_ns != null) {
 79         return error.InvalidArguments;
 80     }
 81     if (parsed.options.since_ns != null and parsed.options.until_ns != null and parsed.options.since_ns.? > parsed.options.until_ns.?) {
 82         return error.InvalidArguments;
 83     }
 84     return parsed;
 85 }
 86 
 87 test "find args parse filters window and grouping" {
 88     const parsed = try parse(&.{
 89         "events.jsonl",
 90         "phase",
 91         "--format",
 92         "jsonl",
 93         "--top",
 94         "12",
 95         "--occurrences",
 96         "4",
 97         "--group",
 98         "parent",
 99         "--sort",
100         "self",
101         "--thread",
102         "7",
103         "--around-ns",
104         "1000",
105         "--window-ns",
106         "200",
107         "--min-duration-ns",
108         "50",
109         "--ignore-case",
110     });
111     try std.testing.expectEqualStrings("events.jsonl", parsed.path);
112     try std.testing.expectEqualStrings("phase", parsed.options.pattern);
113     try std.testing.expectEqual(types.Format.jsonl, parsed.format);
114     try std.testing.expectEqual(@as(usize, 12), parsed.options.top);
115     try std.testing.expectEqual(@as(usize, 4), parsed.options.occurrences);
116     try std.testing.expectEqual(tracy.find.Group.parent, parsed.options.group);
117     try std.testing.expectEqual(tracy.find.Sort.self, parsed.options.sort);
118     try std.testing.expectEqual(@as(?u64, 7), parsed.options.thread);
119     try std.testing.expectEqual(@as(?u64, 900), parsed.options.since_ns);
120     try std.testing.expectEqual(@as(?u64, 1100), parsed.options.until_ns);
121     try std.testing.expectEqual(@as(u64, 50), parsed.options.min_duration_ns);
122     try std.testing.expect(parsed.options.ignore_case);
123 }