lib/tracy/src/cli/args/lock.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.LockArgs {
7 if (args.len == 0) return error.InvalidArguments;
8 var parsed = types.LockArgs{ .path = args[0] };
9 var around_ns: ?u64 = null;
10 var window_ns: ?u64 = null;
11 var index: usize = 1;
12 while (index < args.len) : (index += 1) {
13 if (std.mem.eql(u8, args[index], "--format")) {
14 index += 1;
15 if (index >= args.len) return error.InvalidArguments;
16 if (std.mem.eql(u8, args[index], "text")) {
17 parsed.format = .text;
18 } else if (std.mem.eql(u8, args[index], "jsonl")) {
19 parsed.format = .jsonl;
20 } else {
21 return error.UnsupportedFormat;
22 }
23 } else if (std.mem.eql(u8, args[index], "--top")) {
24 index += 1;
25 if (index >= args.len) return error.InvalidArguments;
26 parsed.options.top = try scalar.parsePositiveUsize(args[index]);
27 } else if (std.mem.eql(u8, args[index], "--occurrences")) {
28 index += 1;
29 if (index >= args.len) return error.InvalidArguments;
30 parsed.options.occurrences = try scalar.parseUsize(args[index]);
31 } else if (std.mem.eql(u8, args[index], "--sort")) {
32 index += 1;
33 if (index >= args.len) return error.InvalidArguments;
34 parsed.options.sort = tracy.locks.Sort.fromName(args[index]) orelse return error.UnsupportedSort;
35 } else if (std.mem.eql(u8, args[index], "--kind")) {
36 index += 1;
37 if (index >= args.len) return error.InvalidArguments;
38 parsed.options.kind = tracy.locks.Kind.fromName(args[index]) orelse return error.UnsupportedKind;
39 } else if (std.mem.eql(u8, args[index], "--mode")) {
40 index += 1;
41 if (index >= args.len) return error.InvalidArguments;
42 parsed.options.mode = tracy.locks.Mode.fromName(args[index]) orelse return error.UnsupportedMode;
43 } else if (std.mem.eql(u8, args[index], "--min-wait-ns")) {
44 index += 1;
45 if (index >= args.len) return error.InvalidArguments;
46 parsed.options.min_wait_ns = try scalar.parseU64(args[index]);
47 } else if (std.mem.eql(u8, args[index], "--min-hold-ns")) {
48 index += 1;
49 if (index >= args.len) return error.InvalidArguments;
50 parsed.options.min_hold_ns = try scalar.parseU64(args[index]);
51 } else if (std.mem.eql(u8, args[index], "--lock")) {
52 index += 1;
53 if (index >= args.len) return error.InvalidArguments;
54 parsed.options.lock = try scalar.parseU64(args[index]);
55 } else if (std.mem.eql(u8, args[index], "--thread")) {
56 index += 1;
57 if (index >= args.len) return error.InvalidArguments;
58 parsed.options.thread = try scalar.parseU64(args[index]);
59 } else if (std.mem.eql(u8, args[index], "--since-ns")) {
60 index += 1;
61 if (index >= args.len) return error.InvalidArguments;
62 parsed.options.since_ns = try scalar.parseU64(args[index]);
63 } else if (std.mem.eql(u8, args[index], "--until-ns")) {
64 index += 1;
65 if (index >= args.len) return error.InvalidArguments;
66 parsed.options.until_ns = try scalar.parseU64(args[index]);
67 } else if (std.mem.eql(u8, args[index], "--around-ns")) {
68 index += 1;
69 if (index >= args.len) return error.InvalidArguments;
70 around_ns = try scalar.parseU64(args[index]);
71 } else if (std.mem.eql(u8, args[index], "--window-ns")) {
72 index += 1;
73 if (index >= args.len) return error.InvalidArguments;
74 window_ns = try scalar.parseU64(args[index]);
75 } else if (std.mem.eql(u8, args[index], "--match")) {
76 index += 1;
77 if (index >= args.len) return error.InvalidArguments;
78 parsed.options.match = args[index];
79 } else if (std.mem.eql(u8, args[index], "--ignore-case")) {
80 parsed.options.ignore_case = true;
81 } else {
82 return error.UnknownArgument;
83 }
84 }
85 if (around_ns) |center| {
86 if (parsed.options.since_ns != null or parsed.options.until_ns != null) return error.InvalidArguments;
87 const width = window_ns orelse 1_000_000;
88 const half = width / 2;
89 parsed.options.since_ns = if (center > half) center - half else 0;
90 parsed.options.until_ns = center +| (width - half);
91 } else if (window_ns != null) {
92 return error.InvalidArguments;
93 }
94 if (parsed.options.since_ns != null and parsed.options.until_ns != null and parsed.options.since_ns.? > parsed.options.until_ns.?) {
95 return error.InvalidArguments;
96 }
97 return parsed;
98 }
99
100 test "lock args parse filters window and mode" {
101 const parsed = try parse(&.{
102 "events.jsonl",
103 "--format",
104 "jsonl",
105 "--top",
106 "12",
107 "--occurrences",
108 "4",
109 "--sort",
110 "wait-tail",
111 "--kind",
112 "wait",
113 "--mode",
114 "shared",
115 "--min-wait-ns",
116 "100",
117 "--min-hold-ns",
118 "200",
119 "--lock",
120 "3",
121 "--thread",
122 "7",
123 "--around-ns",
124 "1000",
125 "--window-ns",
126 "200",
127 "--match",
128 "queue",
129 "--ignore-case",
130 });
131 try std.testing.expectEqualStrings("events.jsonl", parsed.path);
132 try std.testing.expectEqual(types.Format.jsonl, parsed.format);
133 try std.testing.expectEqual(@as(usize, 12), parsed.options.top);
134 try std.testing.expectEqual(@as(usize, 4), parsed.options.occurrences);
135 try std.testing.expectEqual(tracy.locks.Sort.wait_tail, parsed.options.sort);
136 try std.testing.expectEqual(tracy.locks.Kind.wait, parsed.options.kind);
137 try std.testing.expectEqual(tracy.locks.Mode.shared, parsed.options.mode);
138 try std.testing.expectEqual(@as(u64, 100), parsed.options.min_wait_ns);
139 try std.testing.expectEqual(@as(u64, 200), parsed.options.min_hold_ns);
140 try std.testing.expectEqual(@as(?u64, 3), parsed.options.lock);
141 try std.testing.expectEqual(@as(?u64, 7), parsed.options.thread);
142 try std.testing.expectEqual(@as(?u64, 900), parsed.options.since_ns);
143 try std.testing.expectEqual(@as(?u64, 1100), parsed.options.until_ns);
144 try std.testing.expectEqualStrings("queue", parsed.options.match.?);
145 try std.testing.expect(parsed.options.ignore_case);
146 }