summaryrefslogtreecommitdiff
path: root/src/util/enum.zig
blob: 216d04e9ad9c31b5d7684ead0df802e641696908 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const std = @import("std");

pub fn enumFieldsSlice(comptime T: type) []const T {
    var fields: []const T = &[_]T{};
    inline for (@typeInfo(T).Enum.fields) |enumField| {
        fields = fields ++ &[_]T{
            @field(T, enumField.name),
        };
    }
    return fields;
}

/// Creates an slice of slices with with fields in the given enum.
/// Runs `F` for each field in `T` to modify the names in the resulting slice.
pub fn enumFieldsStringSlice(
    comptime T: type,
    comptime F: ?fn (comptime []const u8) []const u8,
) []const []const u8 {
    @setEvalBranchQuota(10000);
    var names: []const []const u8 = &[_][]const u8{};
    for (std.meta.fields(T)) |field| {
        const name = blk: {
            if (F) |f| break :blk f(field.name);
            break :blk field.name;
        };
        names = names ++ &[_][]const u8{name};
    }
    return names;
}

const TestEnum = enum {
    A_A,
    B_B,
};

fn replaceUnderscores(comptime o: []const u8) []const u8 {
    var name: [o.len]u8 = undefined;
    _ = std.mem.replace(u8, o, &[_]u8{'_'}, &[_]u8{'-'}, &name);
    return &name;
}

test "enumFieldsSlice" {
    const fields = comptime enumFieldsSlice(TestEnum);
    try std.testing.expect(fields.len == 2);
    try std.testing.expect(fields[@enumToInt(TestEnum.A_A)] == TestEnum.A_A);
    try std.testing.expect(fields[@enumToInt(TestEnum.B_B)] == TestEnum.B_B);
}

test "enumFieldsStringSlice" {
    const fields = comptime enumFieldsStringSlice(TestEnum, replaceUnderscores);
    const a = TestEnum.A_A;
    const b = TestEnum.B_B;
    try std.testing.expect(fields.len == 2);
    try std.testing.expect(std.mem.eql(u8, fields[@enumToInt(a)], "A-A"));
    try std.testing.expect(std.mem.eql(u8, fields[@enumToInt(b)], "B-B"));
}