Mirror std.json behavior for unions

This commit is contained in:
jaina heartles 2022-12-16 01:02:44 -08:00
parent 38f91dd890
commit 8b1ff1149f
2 changed files with 3 additions and 21 deletions

View file

@ -153,7 +153,7 @@ pub fn openForm(multipart_stream: anytype) MultipartForm(@TypeOf(multipart_strea
fn Deserializer(comptime Result: type) type { fn Deserializer(comptime Result: type) type {
return util.DeserializerContext(Result, MultipartFormField, struct { return util.DeserializerContext(Result, MultipartFormField, struct {
pub const options = .{ .isScalar = isScalar, .embed_unions = true }; pub const options = .{ .isScalar = isScalar };
pub fn isScalar(comptime T: type) bool { pub fn isScalar(comptime T: type) bool {
if (T == FormFile or T == ?FormFile) return true; if (T == FormFile or T == ?FormFile) return true;

View file

@ -40,23 +40,14 @@ pub fn deserializeString(allocator: std.mem.Allocator, comptime T: type, value:
fn getStaticFieldList(comptime T: type, comptime prefix: FieldRef, comptime options: SerializationOptions) []const FieldRef { fn getStaticFieldList(comptime T: type, comptime prefix: FieldRef, comptime options: SerializationOptions) []const FieldRef {
comptime { comptime {
if (std.meta.trait.is(.Union)(T) and prefix.len == 0 and options.embed_unions) {
@compileError("Cannot embed a union into nothing");
}
if (options.isScalar(T)) return &.{prefix}; if (options.isScalar(T)) return &.{prefix};
if (std.meta.trait.is(.Optional)(T)) return getStaticFieldList(std.meta.Child(T), prefix, options); if (std.meta.trait.is(.Optional)(T)) return getStaticFieldList(std.meta.Child(T), prefix, options);
if (std.meta.trait.isSlice(T) and !std.meta.trait.isZigString(T)) return &.{}; if (std.meta.trait.isSlice(T) and !std.meta.trait.isZigString(T)) return &.{};
const eff_prefix: FieldRef = if (std.meta.trait.is(.Union)(T) and options.embed_unions)
prefix[0 .. prefix.len - 1]
else
prefix;
var fields: []const FieldRef = &.{}; var fields: []const FieldRef = &.{};
for (std.meta.fields(T)) |f| { for (std.meta.fields(T)) |f| {
const new_prefix = eff_prefix ++ &[_][]const u8{f.name}; const new_prefix = if (std.meta.trait.is(.Union)(T)) prefix else prefix ++ &[_][]const u8{f.name};
const F = f.field_type; const F = f.field_type;
fields = fields ++ getStaticFieldList(F, new_prefix, options); fields = fields ++ getStaticFieldList(F, new_prefix, options);
} }
@ -67,25 +58,16 @@ fn getStaticFieldList(comptime T: type, comptime prefix: FieldRef, comptime opti
fn getDynamicFieldList(comptime T: type, comptime prefix: FieldRef, comptime options: SerializationOptions) []const DynamicField { fn getDynamicFieldList(comptime T: type, comptime prefix: FieldRef, comptime options: SerializationOptions) []const DynamicField {
comptime { comptime {
if (std.meta.trait.is(.Union)(T) and prefix.len == 0 and options.embed_unions) {
@compileError("Cannot embed a union into nothing");
}
if (options.isScalar(T)) return &.{}; if (options.isScalar(T)) return &.{};
if (std.meta.trait.is(.Optional)(T)) return getDynamicFieldList(std.meta.Child(T), prefix, options); if (std.meta.trait.is(.Optional)(T)) return getDynamicFieldList(std.meta.Child(T), prefix, options);
if (std.meta.trait.isSlice(T) and !std.meta.trait.isZigString(T)) return &.{ if (std.meta.trait.isSlice(T) and !std.meta.trait.isZigString(T)) return &.{
.{ .ref = prefix, .child_type = std.meta.Child(T) }, .{ .ref = prefix, .child_type = std.meta.Child(T) },
}; };
const eff_prefix: FieldRef = if (std.meta.trait.is(.Union)(T) and options.embed_unions)
prefix[0 .. prefix.len - 1]
else
prefix;
var fields: []const DynamicField = &.{}; var fields: []const DynamicField = &.{};
for (std.meta.fields(T)) |f| { for (std.meta.fields(T)) |f| {
const new_prefix = eff_prefix ++ &[_][]const u8{f.name}; const new_prefix = if (std.meta.trait.is(.Union)(T)) prefix else prefix ++ &[_][]const u8{f.name};
const F = f.field_type; const F = f.field_type;
fields = fields ++ getDynamicFieldList(F, new_prefix, options); fields = fields ++ getDynamicFieldList(F, new_prefix, options);
} }