Initializes all fields of the struct with their default value, or zero values if no default value is present. If the field is present in the provided initial values, it will have that value instead. Structs are initialized recursively.
pub fn zeroInit(comptime T: type, init: anytype) T
pub fn zeroInit(comptime T: type, init: anytype) T {
const Init = @TypeOf(init);
switch (@typeInfo(T)) {
.@"struct" => |struct_info| {
switch (@typeInfo(Init)) {
.@"struct" => |init_info| {
if (init_info.is_tuple) {
if (init_info.field_names.len > struct_info.field_names.len) {
@compileError("Tuple initializer has more elements than there are fields in `" ++ @typeName(T) ++ "`");
}
} else {
inline for (init_info.field_names) |field_name| {
if (!@hasField(T, field_name)) {
@compileError("Encountered an initializer for `" ++ field_name ++ "`, but it is not a field of " ++ @typeName(T));
}
}
}
var value: T = if (struct_info.layout == .@"extern") zeroes(T) else undefined;
inline for (
struct_info.field_names,
struct_info.field_types,
struct_info.field_attrs,
0..,
) |f_name, f_type, f_attr, i| {
if (f_attr.@"comptime") {
continue;
}
if (init_info.is_tuple and init_info.field_names.len > i) {
@field(value, f_name) = @field(init, init_info.field_names[i]);
} else if (@hasField(@TypeOf(init), f_name)) {
switch (@typeInfo(f_type)) {
.@"struct" => {
@field(value, f_name) = zeroInit(f_type, @field(init, f_name));
},
else => {
@field(value, f_name) = @field(init, f_name);
},
}
} else if (f_attr.defaultValue(f_type)) |val| {
@field(value, f_name) = val;
} else {
switch (@typeInfo(f_type)) {
.@"struct" => {
@field(value, f_name) = std.mem.zeroInit(f_type, .{});
},
else => {
@field(value, f_name) = std.mem.zeroes(@TypeOf(@field(value, f_name)));
},
}
}
}
return value;
},
else => {
@compileError("The initializer must be a struct");
},
}
},
else => {
@compileError("Can't default init a " ++ @typeName(T));
},
}
}