Allow returning default values on base struct

This commit is contained in:
jaina heartles 2022-12-18 05:19:17 -08:00
parent a0b2e22e32
commit e02c5d99e4
1 changed files with 7 additions and 6 deletions

View File

@ -266,7 +266,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
} }
pub fn finish(self: *@This(), allocator: std.mem.Allocator) !Result { pub fn finish(self: *@This(), allocator: std.mem.Allocator) !Result {
return (try self.deserialize(allocator, Result, self.data, &.{})) orelse return (try self.deserialize(allocator, Result, self.data, &.{}, true)) orelse
if (std.meta.fields(Result).len == 0) if (std.meta.fields(Result).len == 0)
return .{} return .{}
else else
@ -290,6 +290,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
comptime T: type, comptime T: type,
intermediary: anytype, intermediary: anytype,
comptime field_ref: FieldRef, comptime field_ref: FieldRef,
allow_default: bool,
) DeserializeError!?T { ) DeserializeError!?T {
if (comptime Context.options.isScalar(T)) { if (comptime Context.options.isScalar(T)) {
const val = @field(intermediary.static, util.comptimeJoin(".", field_ref)); const val = @field(intermediary.static, util.comptimeJoin(".", field_ref));
@ -304,7 +305,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
var partial_match_found: bool = false; var partial_match_found: bool = false;
inline for (info.fields) |field| { inline for (info.fields) |field| {
const F = field.field_type; const F = field.field_type;
const maybe_value = self.deserialize(allocator, F, intermediary, field_ref) catch |err| switch (err) { const maybe_value = self.deserialize(allocator, F, intermediary, field_ref, false) catch |err| switch (err) {
error.MissingField => blk: { error.MissingField => blk: {
partial_match_found = true; partial_match_found = true;
break :blk @as(?F, null); break :blk @as(?F, null);
@ -333,7 +334,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
inline for (info.fields) |field, i| { inline for (info.fields) |field, i| {
const F = field.field_type; const F = field.field_type;
const new_field_ref = field_ref ++ &[_][]const u8{field.name}; const new_field_ref = field_ref ++ &[_][]const u8{field.name};
const maybe_value = try self.deserialize(allocator, F, intermediary, new_field_ref); const maybe_value = try self.deserialize(allocator, F, intermediary, new_field_ref, false);
if (maybe_value) |v| { if (maybe_value) |v| {
@field(result, field.name) = v; @field(result, field.name) = v;
fields_alloced[i] = true; fields_alloced[i] = true;
@ -350,7 +351,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
} }
if (any_missing and any_explicit) return error.MissingField; if (any_missing and any_explicit) return error.MissingField;
if (!any_explicit) { if (!any_explicit and !allow_default) {
inline for (info.fields) |field, i| { inline for (info.fields) |field, i| {
if (fields_alloced[i]) self.deserializeFree(allocator, @field(result, field.name)); if (fields_alloced[i]) self.deserializeFree(allocator, @field(result, field.name));
} }
@ -369,7 +370,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
var count: usize = 0; var count: usize = 0;
errdefer for (result[0..count]) |res| util.deepFree(allocator, res); errdefer for (result[0..count]) |res| util.deepFree(allocator, res);
for (data.items) |sub, i| { for (data.items) |sub, i| {
result[i] = (try self.deserialize(allocator, info.child, sub, &.{})) orelse return error.SparseSlice; result[i] = (try self.deserialize(allocator, info.child, sub, &.{}, false)) orelse return error.SparseSlice;
} }
return result; return result;
@ -378,7 +379,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime
}, },
// Specifically non-scalar optionals // Specifically non-scalar optionals
.Optional => |info| return try self.deserialize(allocator, info.child, intermediary, field_ref), .Optional => |info| return try self.deserialize(allocator, info.child, intermediary, field_ref, allow_default),
else => @compileError("Unsupported type"), else => @compileError("Unsupported type"),
} }