diff --git a/src/util/serialize.zig b/src/util/serialize.zig index 120ca48..0f49c48 100644 --- a/src/util/serialize.zig +++ b/src/util/serialize.zig @@ -266,7 +266,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime } 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) return .{} else @@ -290,6 +290,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime comptime T: type, intermediary: anytype, comptime field_ref: FieldRef, + allow_default: bool, ) DeserializeError!?T { if (comptime Context.options.isScalar(T)) { 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; inline for (info.fields) |field| { 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: { partial_match_found = true; 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| { const F = field.field_type; 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| { @field(result, field.name) = v; 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_explicit) { + if (!any_explicit and !allow_default) { inline for (info.fields) |field, i| { 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; errdefer for (result[0..count]) |res| util.deepFree(allocator, res); 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; @@ -378,7 +379,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime }, // 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"), }