lib/bench/src/parse.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 pub fn parseU32(text: []const u8) !u32 {
4 return parseUnsigned(u32, text);
5 }
6
7 pub fn parseU64(text: []const u8) !u64 {
8 return parseUnsigned(u64, text);
9 }
10
11 pub fn parseUsize(text: []const u8) !usize {
12 return parseUnsigned(usize, text);
13 }
14
15 pub fn parsePositiveU32(text: []const u8) !u32 {
16 return parsePositiveUnsigned(u32, text);
17 }
18
19 pub fn parsePositiveUsize(text: []const u8) !usize {
20 return parsePositiveUnsigned(usize, text);
21 }
22
23 pub fn parsePositiveU32List(text: []const u8, values: []u32) !usize {
24 return parsePositiveList(u32, text, values);
25 }
26
27 pub fn parsePositiveUsizeList(text: []const u8, values: []usize) !usize {
28 return parsePositiveList(usize, text, values);
29 }
30
31 fn parseUnsigned(comptime Int: type, text: []const u8) !Int {
32 return std.fmt.parseUnsigned(Int, text, 10) catch return error.InvalidArguments;
33 }
34
35 fn parsePositiveUnsigned(comptime Int: type, text: []const u8) !Int {
36 const value = try parseUnsigned(Int, text);
37 if (value == 0) return error.InvalidArguments;
38 return value;
39 }
40
41 fn parsePositiveList(comptime Int: type, text: []const u8, values: []Int) !usize {
42 var parsed_count: usize = 0;
43 var parts = std.mem.splitScalar(u8, text, ',');
44 while (parts.next()) |part| {
45 if (part.len == 0) return error.InvalidArguments;
46 if (parsed_count >= values.len) return error.InvalidArguments;
47 values[parsed_count] = try parsePositiveUnsigned(Int, part);
48 parsed_count += 1;
49 }
50 if (parsed_count == 0) return error.InvalidArguments;
51 return parsed_count;
52 }
53
54 test "parse unsigned integers with InvalidArguments errors" {
55 try std.testing.expectEqual(@as(u32, 0), try parseU32("0"));
56 try std.testing.expectEqual(@as(u32, 42), try parseU32("42"));
57 try std.testing.expectEqual(@as(u64, 42), try parseU64("42"));
58 try std.testing.expectEqual(@as(usize, 42), try parseUsize("42"));
59
60 try std.testing.expectError(error.InvalidArguments, parseU32(""));
61 try std.testing.expectError(error.InvalidArguments, parseU32("nope"));
62 try std.testing.expectError(error.InvalidArguments, parseU32("4294967296"));
63 }
64
65 test "parse positive integers rejects zero" {
66 try std.testing.expectEqual(@as(u32, 7), try parsePositiveU32("7"));
67 try std.testing.expectEqual(@as(usize, 7), try parsePositiveUsize("7"));
68
69 try std.testing.expectError(error.InvalidArguments, parsePositiveU32("0"));
70 try std.testing.expectError(error.InvalidArguments, parsePositiveUsize("0"));
71 }
72
73 test "parse positive lists writes bounded values" {
74 var values: [3]u32 = undefined;
75 const count = try parsePositiveU32List("1,4,16", values[0..]);
76 try std.testing.expectEqual(@as(usize, 3), count);
77 try std.testing.expectEqualSlices(u32, &.{ 1, 4, 16 }, values[0..count]);
78
79 var widths: [2]usize = undefined;
80 const width_count = try parsePositiveUsizeList("32,64", widths[0..]);
81 try std.testing.expectEqual(@as(usize, 2), width_count);
82 try std.testing.expectEqualSlices(usize, &.{ 32, 64 }, widths[0..width_count]);
83
84 try std.testing.expectError(error.InvalidArguments, parsePositiveU32List("", values[0..]));
85 try std.testing.expectError(error.InvalidArguments, parsePositiveU32List("1,,2", values[0..]));
86 try std.testing.expectError(error.InvalidArguments, parsePositiveU32List("1,0", values[0..]));
87 try std.testing.expectError(error.InvalidArguments, parsePositiveU32List("1,2,3,4", values[0..]));
88 }