@@ -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 ;
0 commit comments