How to implement conditional compilation in Zig's switch syntax?

How to control the specific cases of a switch statement based on compile-time conditional variables?

const std = @import("std");

test "switch" {
    const S = std.posix.S;
    const stat: std.posix.Stat = undefined;
    const type_str = switch (stat.mode & S.IFMT) {
        S.IFIFO => "pipe",
        S.IFCHR => "chrdev",
        S.IFDIR => "dir",
        S.IFBLK => "blkdev",
        S.IFREG => "file",
        S.IFLNK => "link",
        S.IFSOCK => "socket",
        // How to impl?
        // It exists when the system is Solaris, and does not exist otherwise.
        S.IFDOOR => "door",
        else => "unknow",
    };
    std.debug.print("type: {s}\n", .{type_str});
}

This can be done in C.

#include <sys/stat.h>
#include <stdio.h>

void test_switch() {
    struct stat buf;
    const char* type_str;
    switch(buf.st_mode & S_IFMT) {
        case S_IFIFO: type_str = "pipe"; break;
        case S_IFCHR: type_str = "chardev"; break;
        case S_IFDIR: type_str = "dir"; break;
        case S_IFBLK: type_str = "blkdev"; break;
        case S_IFREG: type_str = "file"; break;
        case S_IFLNK: type_str = "link"; break;
        case S_IFSOCK: type_str = "socket"; break;
#ifdef S_IFDOOR
        case S_IFDOOR: type_str = "door"; break;
#endif
        default: type_str = "unknow";
    }
   printf("type: %s\n", type_str);
}

I’ve found a method that works. Are there other ways?

test "switch" {
    const S = std.posix.S;
    const stat: std.posix.Stat = undefined;
    const type_str = switch (stat.mode & S.IFMT) {
        S.IFIFO => "pipe",
        S.IFCHR => "chrdev",
        S.IFDIR => "dir",
        S.IFBLK => "blkdev",
        S.IFREG => "file",
        S.IFLNK => "link",
        S.IFSOCK => "socket",
        else => |filetype| str: {
            const HAVE_S_IFDOOR = @hasField(std.posix.S, "IFDOOR");
            if (HAVE_S_IFDOOR and filetype == S.IFDOOR) break :str "door";
            break :str "unknow";
        },
    };
    std.debug.print("type: {s}\n", .{type_str});
}

You have the solution already, but you might prefer this syntax

        else => |filetype| if (@hasField(std.posix.S, "IFDOOR") and filetype == S.IFDOOR)
            "door"
        else
            "unknow",