From db5d7914d82d69021cf303e0ab02b46e0730bf48 Mon Sep 17 00:00:00 2001 From: Christian Segundo Date: Thu, 15 Jun 2023 19:54:16 +0200 Subject: one step closer --- src/util/struct.zig | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/util/struct.zig (limited to 'src/util/struct.zig') diff --git a/src/util/struct.zig b/src/util/struct.zig new file mode 100644 index 0000000..db41b09 --- /dev/null +++ b/src/util/struct.zig @@ -0,0 +1,85 @@ +const std = @import("std"); + +/// Maps each field of a struct `S` to the enum value in `E` +pub fn StructFieldsMap( + comptime S: type, + comptime E: type, +) type { + const KV = struct { []const u8, E }; + var slice: []const KV = &[_]KV{}; + var idx: usize = 0; + for (std.meta.fields(S)) |field| { + slice = slice ++ &[_]KV{.{ field.name, @intToEnum(E, idx) }}; + idx += 1; + } + return std.ComptimeStringMap(E, slice); +} + +/// Creates an enum with fields matching each field in struct `S`. +/// Runs `F` for each field in `S` to modify the names in the resulting enum. +// sort of opposite to the included EnumFieldStruct in std +pub fn StructFieldsEnum( + comptime S: type, + comptime F: ?fn (comptime []const u8) []const u8, +) type { + const EnumField = std.builtin.Type.EnumField; + var fields: []const EnumField = &[_]EnumField{}; + var idx: usize = 0; + for (std.meta.fields(S)) |field| { + fields = fields ++ &[_]EnumField{.{ + .name = blk: { + if (F) |f| break :blk f(field.name); + break :blk field.name; + }, + .value = idx, + }}; + idx += 1; + } + return @Type(.{ .Enum = .{ + .tag_type = usize, + .fields = fields, + .decls = &.{}, + .is_exhaustive = true, + } }); +} + +const TestStruct = struct { + a_a: bool, + b_b: bool, +}; + +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 "StructFieldsEnum" { + { + const e = StructFieldsEnum(TestStruct, null); + try std.testing.expect(std.mem.eql(u8, std.meta.fields(e)[0].name, "a_a")); + try std.testing.expect(std.mem.eql(u8, std.meta.fields(e)[1].name, "b_b")); + } + + { + const e = StructFieldsEnum(TestStruct, replaceUnderscores); + try std.testing.expect(std.mem.eql(u8, std.meta.fields(e)[0].name, "a-a")); + try std.testing.expect(std.mem.eql(u8, std.meta.fields(e)[1].name, "b-b")); + } +} + +test "StructFieldsMap" { + { + const e = StructFieldsEnum(TestStruct, null); + const map = StructFieldsMap(TestStruct, e); + try std.testing.expect(std.mem.eql(u8, @tagName(map.get("a_a").?), "a_a")); + try std.testing.expect(std.mem.eql(u8, @tagName(map.get("b_b").?), "b_b")); + } + + { + const e = StructFieldsEnum(TestStruct, replaceUnderscores); + const map = StructFieldsMap(TestStruct, e); + try std.testing.expect(std.mem.eql(u8, @tagName(map.get("a_a").?), "a-a")); + try std.testing.expect(std.mem.eql(u8, @tagName(map.get("b_b").?), "b-b")); + } +} -- cgit v1.2.3