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 }