From c74d615131c6fc5c93206bc7543459616c6c947a Mon Sep 17 00:00:00 2001 From: torque Date: Tue, 18 Jun 2024 18:30:27 -0700 Subject: [PATCH] parser.value.convertTo: simplify struct field usage This avoids having to clone the map while maintaining the same conversion strictness. --- src/parser/value.zig | 47 +++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/src/parser/value.zig b/src/parser/value.zig index f1795b4..9fd5603 100644 --- a/src/parser/value.zig +++ b/src/parser/value.zig @@ -209,39 +209,24 @@ pub const Value = union(enum) { .map, .inline_map => |map| { var result: T = undefined; - if (options.ignore_extra_fields) { - inline for (stt.fields) |field| { - if (map.get(field.name)) |value| { - @field(result, field.name) = try value.convertTo(field.type, allocator, options); - } else if (options.allow_omitting_default_values) { - if (comptime field.default_value) |def| - @field(result, field.name) = @as(*align(1) const field.type, @ptrCast(def)).* - else - return error.BadValue; - } else { + if (!options.ignore_extra_fields and (map.count() > stt.fields.len)) + return error.BadValue; + + var use_count: usize = 0; + inline for (stt.fields) |field| { + if (map.get(field.name)) |val| { + @field(result, field.name) = try val.convertTo(field.type, allocator, options); + use_count += 1; + } else if (options.allow_omitting_default_values) { + if (comptime field.default_value) |def| + @field(result, field.name) = @as(*align(1) const field.type, @ptrCast(def)).* + else return error.BadValue; - } - } - } else { - // TODO: consider not cloning the map here. This would - // result in the requirement that the raw value object - // not be used after it has been converted to a type, - // based on the parse options. - var clone = try map.clone(); - defer clone.deinit(); - inline for (stt.fields) |field| { - if (clone.fetchSwapRemove(field.name)) |kv| { - @field(result, field.name) = try kv.value.convertTo(field.type, allocator, options); - } else if (options.allow_omitting_default_values) { - if (comptime field.default_value) |def| - @field(result, field.name) = @as(*align(1) const field.type, @ptrCast(def)).* - else - return error.BadValue; - } else return error.BadValue; - } - // there were extra fields in the data - if (clone.count() > 0) return error.BadValue; + } else return error.BadValue; } + // there were extra fields in the data + if (!options.ignore_extra_fields and (map.count() > use_count)) + return error.BadValue; return result; },