std.mem.zeroInit: Fix behaviour with empty initialiser

This commit is contained in:
ominitay 2022-03-28 12:10:36 +01:00 committed by GitHub
parent 460e7a2445
commit 25d4c5df70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -432,6 +432,13 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
.Struct => |init_info| {
var value = std.mem.zeroes(T);
inline for (struct_info.fields) |field| {
if (field.default_value) |default_value_ptr| {
const default_value = @ptrCast(*const field.field_type, default_value_ptr).*;
@field(value, field.name) = default_value;
}
}
if (init_info.is_tuple) {
inline for (init_info.fields) |field, i| {
@field(value, struct_info.fields[i].name) = @field(init, field.name);
@ -443,21 +450,14 @@ pub fn zeroInit(comptime T: type, init: anytype) T {
if (!@hasField(T, field.name)) {
@compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T));
}
}
inline for (struct_info.fields) |field| {
if (@hasField(Init, field.name)) {
switch (@typeInfo(field.field_type)) {
.Struct => {
@field(value, field.name) = zeroInit(field.field_type, @field(init, field.name));
},
else => {
@field(value, field.name) = @field(init, field.name);
},
}
} else if (field.default_value) |default_value_ptr| {
const default_value = @ptrCast(*const field.field_type, default_value_ptr).*;
@field(value, field.name) = default_value;
switch (@typeInfo(field.field_type)) {
.Struct => {
@field(value, field.name) = zeroInit(field.field_type, @field(init, field.name));
},
else => {
@field(value, field.name) = @field(init, field.name);
},
}
}
@ -515,6 +515,28 @@ test "zeroInit" {
.b = 0,
.a = 0,
}, c);
const Foo = struct {
foo: u8 = 69,
bar: u8,
};
const f = zeroInit(Foo, .{});
try testing.expectEqual(Foo{
.foo = 69,
.bar = 0,
}, f);
const Bar = struct {
foo: u32 = 666,
bar: u32 = 420,
};
const b = zeroInit(Bar, .{69});
try testing.expectEqual(Bar{
.foo = 69,
.bar = 420,
}, b);
}
/// Compares two slices of numbers lexicographically. O(n).