diff --git a/src/util/serialize.zig b/src/util/serialize.zig index 0cf2324..0cc7a05 100644 --- a/src/util/serialize.zig +++ b/src/util/serialize.zig @@ -82,39 +82,42 @@ const DynamicField = struct { }; pub const SerializationOptions = struct { - embed_unions: bool, isScalar: fn (type) bool, }; pub const default_options = SerializationOptions{ - .embed_unions = true, .isScalar = defaultIsScalar, }; fn StaticIntermediary(comptime Result: type, comptime From: type, comptime options: SerializationOptions) type { const field_refs = getStaticFieldList(Result, &.{}, options); - var fields: [field_refs.len + 1]std.builtin.Type.StructField = undefined; - for (field_refs) |ref, i| { - fields[i] = .{ - .name = util.comptimeJoin(".", ref), + // avert compiler crash by having at least one field + var fields = [_]std.builtin.Type.StructField{.{ + .name = "__dummy", + .default_value = &{}, + .field_type = void, + .is_comptime = false, + .alignment = 0, + }} ** (field_refs.len + 1); + + var count: usize = 1; + outer: for (field_refs) |ref| { + const name = util.comptimeJoin(".", ref); + for (fields[0..count]) |f| if (std.mem.eql(u8, f.name, name)) continue :outer; + fields[count] = .{ + .name = name, .field_type = ?From, .default_value = &@as(?From, null), .is_comptime = false, .alignment = @alignOf(?From), }; + count += 1; } - fields[fields.len - 1] = .{ - .name = "__dummy", - .default_value = &1, - .field_type = usize, - .is_comptime = false, - .alignment = @alignOf(usize), - }; return @Type(.{ .Struct = .{ .layout = .Auto, - .fields = &fields, + .fields = fields[0..count], .decls = &.{}, .is_tuple = false, } }); @@ -123,28 +126,33 @@ fn StaticIntermediary(comptime Result: type, comptime From: type, comptime optio fn DynamicIntermediary(comptime Result: type, comptime From: type, comptime options: SerializationOptions) type { const field_refs = getDynamicFieldList(Result, &.{}, options); - var fields: [field_refs.len + 1]std.builtin.Type.StructField = undefined; - for (field_refs) |f, i| { - const T = std.ArrayListUnmanaged(Intermediary(f.child_type, From, options)); - fields[i] = .{ - .name = util.comptimeJoin(".", f.ref), + var fields = [_]std.builtin.Type.StructField{.{ + .name = "__dummy", + .default_value = &{}, + .field_type = void, + .is_comptime = false, + .alignment = 0, + }} ** (field_refs.len + 1); + + var count: usize = 1; + outer: for (field_refs) |ref| { + const name = util.comptimeJoin(".", ref.ref); + for (fields[0..count]) |f| if (std.mem.eql(u8, f.name, name)) continue :outer; + + const T = std.ArrayListUnmanaged(Intermediary(ref.child_type, From, options)); + fields[count] = .{ + .name = name, .default_value = &T{}, .field_type = T, .is_comptime = false, .alignment = @alignOf(T), }; + count += 1; } - fields[fields.len - 1] = .{ - .name = "__dummy", - .default_value = &1, - .field_type = usize, - .is_comptime = false, - .alignment = @alignOf(usize), - }; return @Type(.{ .Struct = .{ .layout = .Auto, - .fields = &fields, + .fields = fields[0..count], .decls = &.{}, .is_tuple = false, } });