| ... | @@ -431,34 +431,48 @@ pub fn zeroInit(comptime T: type, init: anytype) T { | ... | @@ -431,34 +431,48 @@ pub fn zeroInit(comptime T: type, init: anytype) T { |
| 431 | .Struct => |struct_info| { | 431 | .Struct => |struct_info| { |
| 432 | switch (@typeInfo(Init)) { | 432 | switch (@typeInfo(Init)) { |
| 433 | .Struct => |init_info| { | 433 | .Struct => |init_info| { |
| 434 | var value = std.mem.zeroes(T); | | |
| 435 | | | |
| 436 | inline for (struct_info.fields) |field| { | | |
| 437 | if (field.default_value) |default_value_ptr| { | | |
| 438 | const default_value = @ptrCast(*align(1) const field.type, default_value_ptr).*; | | |
| 439 | @field(value, field.name) = default_value; | | |
| 440 | } | | |
| 441 | } | | |
| 442 | | | |
| 443 | if (init_info.is_tuple) { | 434 | if (init_info.is_tuple) { |
| 444 | inline for (init_info.fields) |field, i| { | 435 | if (init_info.fields.len > struct_info.fields.len) { |
| 445 | @field(value, struct_info.fields[i].name) = @field(init, field.name); | 436 | @compileError("Tuple initializer has more elments than there are fields in `" ++ @typeName(T) ++ "`"); |
| | 437 | } |
| | 438 | } else { |
| | 439 | inline for (init_info.fields) |field| { |
| | 440 | if (!@hasField(T, field.name)) { |
| | 441 | @compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T)); |
| | 442 | } |
| 446 | } | 443 | } |
| 447 | return value; | | |
| 448 | } | 444 | } |
| 449 | | 445 | |
| 450 | inline for (init_info.fields) |field| { | 446 | var value: T = undefined; |
| 451 | if (!@hasField(T, field.name)) { | 447 | |
| 452 | @compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T)); | 448 | inline for (struct_info.fields) |field, i| { |
| | 449 | if (field.is_comptime) { |
| | 450 | continue; |
| 453 | } | 451 | } |
| 454 | | 452 | |
| 455 | switch (@typeInfo(field.type)) { | 453 | if (init_info.is_tuple and init_info.fields.len > i) { |
| 456 | .Struct => { | 454 | @field(value, field.name) = @field(init, init_info.fields[i].name); |
| 457 | @field(value, field.name) = zeroInit(field.type, @field(init, field.name)); | 455 | } else if (@hasField(@TypeOf(init), field.name)) { |
| 458 | }, | 456 | switch (@typeInfo(field.type)) { |
| 459 | else => { | 457 | .Struct => { |
| 460 | @field(value, field.name) = @field(init, field.name); | 458 | @field(value, field.name) = zeroInit(field.type, @field(init, field.name)); |
| 461 | }, | 459 | }, |
| | 460 | else => { |
| | 461 | @field(value, field.name) = @field(init, field.name); |
| | 462 | }, |
| | 463 | } |
| | 464 | } else if (field.default_value) |default_value_ptr| { |
| | 465 | const default_value = @ptrCast(*align(1) const field.type, default_value_ptr).*; |
| | 466 | @field(value, field.name) = default_value; |
| | 467 | } else { |
| | 468 | switch (@typeInfo(field.type)) { |
| | 469 | .Struct => { |
| | 470 | @field(value, field.name) = std.mem.zeroInit(field.type, .{}); |
| | 471 | }, |
| | 472 | else => { |
| | 473 | @field(value, field.name) = std.mem.zeroes(@TypeOf(@field(value, field.name))); |
| | 474 | }, |
| | 475 | } |
| 462 | } | 476 | } |
| 463 | } | 477 | } |
| 464 | | 478 | |
| ... | @@ -538,6 +552,24 @@ test "zeroInit" { | ... | @@ -538,6 +552,24 @@ test "zeroInit" { |
| 538 | .foo = 69, | 552 | .foo = 69, |
| 539 | .bar = 420, | 553 | .bar = 420, |
| 540 | }, b); | 554 | }, b); |
| | 555 | |
| | 556 | const Baz = struct { |
| | 557 | foo: [:0]const u8 = "bar", |
| | 558 | }; |
| | 559 | |
| | 560 | const baz1 = zeroInit(Baz, .{}); |
| | 561 | try testing.expectEqual(Baz{}, baz1); |
| | 562 | |
| | 563 | const baz2 = zeroInit(Baz, .{ .foo = "zab" }); |
| | 564 | try testing.expectEqualSlices(u8, "zab", baz2.foo); |
| | 565 | |
| | 566 | const NestedBaz = struct { |
| | 567 | bbb: Baz, |
| | 568 | }; |
| | 569 | const nested_baz = zeroInit(NestedBaz, .{}); |
| | 570 | try testing.expectEqual(NestedBaz{ |
| | 571 | .bbb = Baz{}, |
| | 572 | }, nested_baz); |
| 541 | } | 573 | } |
| 542 | | 574 | |
| 543 | /// Compares two slices of numbers lexicographically. O(n). | 575 | /// Compares two slices of numbers lexicographically. O(n). |