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