Open1

Zig comptime 実例集

smallkirbysmallkirby

@unionInit() x inline else

バイナリデータを扱うコードではありがちな、「バイト列を指すポインタがあり、そのバイト列が表すデータ型はヘッダの値に応じて変わる」というパターン。判明したデータ型に応じて、そのバイト列を指すポインタを具体的なデータ型に変換する関数:

const DataType = enum(u8) { a, b, c };
const Data = union(DataType) {
    a: *align(1) packed struct {...},
    b: *align(1) packed struct {...},
    c: *align(1) packed struct {...},
};

fn getData(bytes: [*]u8, data_type: DataType) Data {
    return switch (data_type) {
        inline else => |t| @unionInit(
            Data,
            @tagName(t),
            @alignCast(@ptrCast(bytes)),
        )
    };
}

@unionInit()union の初期化において、active なフィールドの指定をトークンではなく comptime な文字列で行える。
inline else@tagName() で全てのフィールドのタグ文字列に対し共通して union の初期化ができる。愚直にやると全てのフィールドに対する case を列挙する必要があったり、もしくは inline for (std.meta.fields(DataType)) とする必要があるが、これならシンプル。

用例

参考