const std = @import("std"); const expect = std.testing.expect; const os = std.Target.current.os.tag; test "switch simple" { const a: u64 = 10; const zz: u64 = 103; // All branches of a switch expression must be able to be coerced // to a common type. Branches cannot fallthrough. If fallthrough behavior // is desired, combine the cases and use an if. const b = switch (a) { // Multiple cases can be combined via a ',' 1, 2, 3 => 0, // Ranges can be specified using the ... syntax. // These are inclusive both ends. 5...100 => 1, // Branches can be arbitrarily complex. 101 => blk: { const c: u64 = 5; break :blk c * 2 + 1; }, // Switching on arbitrary expressions is allowed as long as the // expression is known at compile-time. zz => zz, blk: { const d: u32 = 5; const e: u32 = 100; break :blk d + e; } => 107, // The else branch catches everything not already captured. // Else branches are mandatory unless the entire range of values // is handled. else => 9, }; expect(b == 1); } // Switch expressions can be used outside a function: const os_msg = switch (os) { .linux => "we found a linux user", else => "not a linux user", }; // Inside a function, switch statements implicitly are compile-time // evaluated if the target expression is compile-time known. test "switch inside function" { switch (os) { // On an OS other than fuchsia, block is not even analyzed, // so this compile error is not triggered. // On fuchsia this compile error would be triggered. .fuchsia => @compileError("fuchsia not supported"), else => {}, } } test "switch on tagged union" { const Point = struct { x: u8, y: u8 }; const Item = union(enum) { a: u32, c: Point, d, e: u32 }; var a = Item{ .c = Point{ .x = 1, .y = 2 } }; // Switching on more complex enums is allowed. const b = switch (a) { // A capture group is allowed on a match, and will return the enum // value matched. If the payload types of both cases are the same // they can be put into the same switch prong. Item.a, Item.e => |item| item, // A reference to the matched value can be obtained using `*` syntax. Item.c => |*item| blk: { item.*.x += 1; break :blk 6; }, // No else is required if the types cases was exhaustively handled Item.d => 8, }; expect(b == 6); expect(a.c.x == 2); }