core: address review comments

- break formatting values out into a function so that we can
  catch errors and never fail
- eliminate the use of toOwnedSentinelSlice since we are using
  an arena to clean up memory
This commit is contained in:
Jeffrey C. Ollie
2024-11-09 12:49:40 -06:00
parent ca844ca3c0
commit 3eef6d205e

View File

@ -132,12 +132,55 @@ pub fn parse(
// track more error messages.
error.OutOfMemory => return err,
error.InvalidField => "unknown field",
error.ValueRequired => "value required",
error.InvalidValue => msg: {
error.ValueRequired => formatValueRequired(T, arena_alloc, key) catch "value required",
error.InvalidValue => formatInvalidValue(T, arena_alloc, key, value) catch "invalid value",
else => try std.fmt.allocPrintZ(
arena_alloc,
"unknown error {}",
.{err},
),
};
// Add our diagnostic
try dst._diagnostics.append(arena_alloc, .{
.key = try arena_alloc.dupeZ(u8, key),
.message = message,
.location = diags.Location.fromIter(iter),
});
};
}
}
fn formatValueRequired(
comptime T: type,
arena_alloc: std.mem.Allocator,
key: []const u8,
) std.mem.Allocator.Error![:0]const u8 {
var buf = std.ArrayList(u8).init(arena_alloc);
errdefer buf.deinit();
const writer = buf.writer();
try writer.print("value required", .{});
try formatValues(T, key, writer);
try writer.writeByte(0);
return buf.items[0 .. buf.items.len - 1 :0];
}
fn formatInvalidValue(
comptime T: type,
arena_alloc: std.mem.Allocator,
key: []const u8,
value: ?[]const u8,
) std.mem.Allocator.Error![:0]const u8 {
var buf = std.ArrayList(u8).init(arena_alloc);
errdefer buf.deinit();
const writer = buf.writer();
try writer.print("invalid value \"{?s}\"", .{value});
try formatValues(T, key, writer);
try writer.writeByte(0);
return buf.items[0 .. buf.items.len - 1 :0];
}
fn formatValues(comptime T: type, key: []const u8, writer: anytype) std.mem.Allocator.Error!void {
const typeinfo = @typeInfo(T);
inline for (typeinfo.Struct.fields) |f| {
if (std.mem.eql(u8, key, f.name)) {
@ -154,23 +197,6 @@ pub fn parse(
break;
}
}
break :msg try buf.toOwnedSliceSentinel(0);
},
else => try std.fmt.allocPrintZ(
arena_alloc,
"unknown error {}",
.{err},
),
};
// Add our diagnostic
try dst._diagnostics.append(arena_alloc, .{
.key = try arena_alloc.dupeZ(u8, key),
.message = message,
.location = diags.Location.fromIter(iter),
});
};
}
}
/// Returns true if this type can track diagnostics.