this repo has no description

generic metadata parsing

altagos.dev e0d67a20 2b0458e3

verified
+46 -21
+46 -21
src/austin.zig
··· 74 74 multiprocess: bool = false, 75 75 duration: usize = 0, 76 76 gc: ?usize = null, 77 + 78 + // Add metadata about which fields signal end of parsing 79 + const EndFields = std.StaticStringMap(void).initComptime(.{ 80 + .{"duration"}, .{"gc"}, 81 + }); 82 + 83 + pub fn parseField(self: *Metadata, field_name: []const u8, value: []const u8) !bool { 84 + // Returns true if this field signals end of parsing 85 + 86 + // Use comptime reflection to generate parsing for each field 87 + inline for (std.meta.fields(Metadata)) |field| { 88 + if (std.mem.eql(u8, field_name, field.name)) { 89 + const field_ptr = &@field(self, field.name); 90 + 91 + switch (field.type) { 92 + std.SemanticVersion => { 93 + field_ptr.* = try std.SemanticVersion.parse(value); 94 + }, 95 + usize => { 96 + field_ptr.* = try std.fmt.parseUnsigned(usize, value, 0); 97 + }, 98 + bool => { 99 + field_ptr.* = std.mem.eql(u8, "on", value); 100 + }, 101 + @TypeOf(self.mode) => { 102 + field_ptr.* = std.meta.stringToEnum(@TypeOf(self.mode), value) orelse return error.UnknownMetadataFieldValue; 103 + }, 104 + ?usize => { 105 + field_ptr.* = try std.fmt.parseUnsigned(usize, value, 0); 106 + }, 107 + else => @compileError("Unsupported metadata field type: " ++ @typeName(field.type)), 108 + } 109 + 110 + return EndFields.has(field.name); 111 + } 112 + } 113 + 114 + return error.UnknownMetadataField; 115 + } 77 116 }; 78 117 79 118 const MetadataFields = std.meta.FieldEnum(Metadata); ··· 149 188 const input = mem.trimStart(u8, line.items, "# "); 150 189 var it = mem.tokenizeScalar(u8, input, ':'); 151 190 152 - const key = std.meta.stringToEnum( 153 - MetadataFields, 154 - it.next() orelse return error.MissingKey, 155 - ) orelse return error.UnknownMetadataField; 191 + const key = it.next() orelse return error.MissingKey; 156 192 const value = mem.trimStart(u8, it.next() orelse return error.MissingValue, " "); 157 193 158 - switch (key) { 159 - .austin => profile.meta.austin = try .parse(value), 160 - .interval => profile.meta.interval = try std.fmt.parseUnsigned(usize, value, 0), 161 - .memory => profile.meta.memory = try std.fmt.parseUnsigned(usize, value, 0), 162 - .mode => profile.meta.mode = std.meta.stringToEnum( 163 - @TypeOf(profile.meta.mode), 164 - value, 165 - ) orelse return error.UnknownMetadataFieldValue, 166 - .multiprocess => profile.meta.multiprocess = std.mem.eql(u8, "on", value), 167 - .duration => { 168 - profile.meta.duration = try std.fmt.parseUnsigned(usize, value, 0); 169 - reached_end = true; 170 - }, 171 - .gc => { 172 - profile.meta.gc = try std.fmt.parseUnsigned(usize, value, 0); 173 - reached_end = true; 194 + reached_end = profile.meta.parseField(key, value) catch |err| switch (err) { 195 + error.UnknownMetadataField => { 196 + log.warn("Unknown metadata field: {s}", .{key}); 197 + continue; 174 198 }, 175 - } 199 + else => return err, 200 + }; 176 201 } else { 177 202 // Sample 178 203 const sample = self.parseSample(line, line_num) catch |err| {