A SpaceTraders Agent
1pub fn CombinedEnum(comptime parent: type) type {
2 const parent_info = @typeInfo(parent).@"struct";
3
4 comptime var num_fields = 0;
5 comptime var num_enums = 0;
6
7 inline for (parent_info.decls) |partial| {
8 switch (@typeInfo(@field(parent, partial.name))) {
9 .@"enum" => |e| {
10 num_fields += e.fields.len;
11 num_enums += 1;
12 },
13 else => {},
14 }
15 }
16
17 const ConversionMap = struct {
18 start: comptime_int = 0,
19 end: comptime_int = 0,
20 T: type,
21 };
22
23 comptime var combined: [num_fields][:0]const u8 = undefined;
24 comptime var combined_values: [num_fields]u8 = undefined;
25 comptime var conv_map: [num_enums]ConversionMap = undefined;
26
27 comptime var idx = 0;
28 comptime var i = 0;
29
30 inline for (parent_info.decls) |partial| {
31 switch (@typeInfo(@field(parent, partial.name))) {
32 .@"enum" => |e| {
33 conv_map[idx] = .{
34 .start = i,
35 .end = i + e.fields.len - 1,
36 .T = @field(parent, partial.name),
37 };
38
39 for (e.fields) |field| {
40 combined[i] = field.name;
41 combined_values[i] = field.value;
42 i += 1;
43 }
44
45 idx += 1;
46 },
47 else => {},
48 }
49 }
50
51 const combined_enum = @Enum(
52 u8,
53 .nonexhaustive,
54 &combined,
55 &combined_values,
56 );
57
58 return struct {
59 pub const Combined = combined_enum;
60
61 const conversion_map: [num_enums]ConversionMap = conv_map;
62
63 pub fn originalType(value: @TypeOf(Combined)) type {
64 const int_rep: u8 = @intFromEnum(value);
65
66 for (conversion_map) |map| {
67 if (map.start <= int_rep and int_rep <= map.end) return map.T;
68 }
69 }
70 };
71}