authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-01 14:47:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-01 14:47:55-04:00
logf9b220ec2c5203fc70bab3b872cf6cd100651357
tree68af6ca926b52a367576c2b8b7504f71e1b06729
parent937dcad0b3802863af0891b2766acb55f89949ba
parent109c0b9d96ba0b1d421190d38fa67a97d4184d6b

Merge branch 'brodeuralexis-zero-init-helper'

closes #5472

1 files changed, 74 insertions(+), 0 deletions(-)

lib/std/mem.zig+74
......@@ -516,6 +516,80 @@ test "mem.secureZero" {
516516 testing.expectEqualSlices(u8, a[0..], b[0..]);
517517}
518518
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.
522pub 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
565test "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
519593pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order {
520594 const n = math.min(lhs.len, rhs.len);
521595 var i: usize = 0;