Deduplicate union fields

This commit is contained in:
jaina heartles 2022-12-16 01:03:23 -08:00
parent 8b1ff1149f
commit cd311cfa3c
1 changed files with 35 additions and 27 deletions

View File

@ -82,39 +82,42 @@ const DynamicField = struct {
}; };
pub const SerializationOptions = struct { pub const SerializationOptions = struct {
embed_unions: bool,
isScalar: fn (type) bool, isScalar: fn (type) bool,
}; };
pub const default_options = SerializationOptions{ pub const default_options = SerializationOptions{
.embed_unions = true,
.isScalar = defaultIsScalar, .isScalar = defaultIsScalar,
}; };
fn StaticIntermediary(comptime Result: type, comptime From: type, comptime options: SerializationOptions) type { fn StaticIntermediary(comptime Result: type, comptime From: type, comptime options: SerializationOptions) type {
const field_refs = getStaticFieldList(Result, &.{}, options); const field_refs = getStaticFieldList(Result, &.{}, options);
var fields: [field_refs.len + 1]std.builtin.Type.StructField = undefined; // avert compiler crash by having at least one field
for (field_refs) |ref, i| { var fields = [_]std.builtin.Type.StructField{.{
fields[i] = .{ .name = "__dummy",
.name = util.comptimeJoin(".", ref), .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, .field_type = ?From,
.default_value = &@as(?From, null), .default_value = &@as(?From, null),
.is_comptime = false, .is_comptime = false,
.alignment = @alignOf(?From), .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 = .{ return @Type(.{ .Struct = .{
.layout = .Auto, .layout = .Auto,
.fields = &fields, .fields = fields[0..count],
.decls = &.{}, .decls = &.{},
.is_tuple = false, .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 { fn DynamicIntermediary(comptime Result: type, comptime From: type, comptime options: SerializationOptions) type {
const field_refs = getDynamicFieldList(Result, &.{}, options); const field_refs = getDynamicFieldList(Result, &.{}, options);
var fields: [field_refs.len + 1]std.builtin.Type.StructField = undefined; var fields = [_]std.builtin.Type.StructField{.{
for (field_refs) |f, i| { .name = "__dummy",
const T = std.ArrayListUnmanaged(Intermediary(f.child_type, From, options)); .default_value = &{},
fields[i] = .{ .field_type = void,
.name = util.comptimeJoin(".", f.ref), .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{}, .default_value = &T{},
.field_type = T, .field_type = T,
.is_comptime = false, .is_comptime = false,
.alignment = @alignOf(T), .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 = .{ return @Type(.{ .Struct = .{
.layout = .Auto, .layout = .Auto,
.fields = &fields, .fields = fields[0..count],
.decls = &.{}, .decls = &.{},
.is_tuple = false, .is_tuple = false,
} }); } });