| ... | ... | @@ -516,6 +516,80 @@ test "mem.secureZero" { |
| 516 | 516 | testing.expectEqualSlices(u8, a[0..], b[0..]); |
| 517 | 517 | } |
| 518 | 518 | |
| 519 | /// Initializes all fields of the struct with their default value, or zero values if no default value is present. |
| 520 | /// If the field is present in the provided initial values, it will have that value instead. |
| 521 | /// Structs are initialized recursively. |
| 522 | pub fn zeroInit(comptime T: type, init: var) T { |
| 523 | comptime const Init = @TypeOf(init); |
| 524 | |
| 525 | switch (@typeInfo(T)) { |
| 526 | .Struct => |struct_info| { |
| 527 | switch (@typeInfo(Init)) { |
| 528 | .Struct => |init_info| { |
| 529 | var value = std.mem.zeroes(T); |
| 530 | |
| 531 | inline for (init_info.fields) |field| { |
| 532 | if (!@hasField(T, field.name)) { |
| 533 | @compileError("Encountered an initializer for `" ++ field.name ++ "`, but it is not a field of " ++ @typeName(T)); |
| 534 | } |
| 535 | } |
| 536 | |
| 537 | inline for (struct_info.fields) |field| { |
| 538 | if (@hasField(Init, field.name)) { |
| 539 | switch (@typeInfo(field.field_type)) { |
| 540 | .Struct => { |
| 541 | @field(value, field.name) = zeroInit(field.field_type, @field(init, field.name)); |
| 542 | }, |
| 543 | else => { |
| 544 | @field(value, field.name) = @field(init, field.name); |
| 545 | }, |
| 546 | } |
| 547 | } else if (field.default_value != null) { |
| 548 | @field(value, field.name) = field.default_value; |
| 549 | } |
| 550 | } |
| 551 | |
| 552 | return value; |
| 553 | }, |
| 554 | else => { |
| 555 | @compileError("The initializer must be a struct"); |
| 556 | }, |
| 557 | } |
| 558 | }, |
| 559 | else => { |
| 560 | @compileError("Can't default init a " ++ @typeName(T)); |
| 561 | }, |
| 562 | } |
| 563 | } |
| 564 | |
| 565 | test "zeroInit" { |
| 566 | const I = struct { |
| 567 | d: f64, |
| 568 | }; |
| 569 | |
| 570 | const S = struct { |
| 571 | a: u32, |
| 572 | b: ?bool, |
| 573 | c: I, |
| 574 | e: [3]u8, |
| 575 | f: i64, |
| 576 | }; |
| 577 | |
| 578 | const s = zeroInit(S, .{ |
| 579 | .a = 42, |
| 580 | }); |
| 581 | |
| 582 | testing.expectEqual(s, S{ |
| 583 | .a = 42, |
| 584 | .b = null, |
| 585 | .c = .{ |
| 586 | .d = 0, |
| 587 | }, |
| 588 | .e = [3]u8{ 0, 0, 0 }, |
| 589 | .f = 0, |
| 590 | }); |
| 591 | } |
| 592 | |
| 519 | 593 | pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order { |
| 520 | 594 | const n = math.min(lhs.len, rhs.len); |
| 521 | 595 | var i: usize = 0; |