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 std = @import("std");
7 const parent_info = @typeInfo(parent).@"struct";
8
9 var num_fields = 0;
10 var num_enums = 0;
11
12 for (parent_info.decls) |partial| {
13 switch (@typeInfo(@field(parent, partial.name))) {
14 .@"enum" => |e| {
15 num_fields += e.fields.len;
16 num_enums += 1;
17 },
18 else => {},
19 }
20 }
21
22 const ConversionMap = struct {
23 start: comptime_int = 0,
24 end: comptime_int = 0,
25 T: type,
26 };
27
28 var combined: [num_fields]std.builtin.Type.EnumField = 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] = .{ .name = field.name, .value = field.value };
45 i += 1;
46 }
47
48 idx += 1;
49 },
50 else => {},
51 }
52 }
53
54 const combined_enum = @Type(std.builtin.Type{ .@"enum" = .{
55 .decls = &.{},
56 .fields = &combined,
57 .tag_type = u8,
58 .is_exhaustive = true,
59 } });
60
61 const combined_enums = num_enums;
62 const conv_map_const = conv_map;
63
64 return struct {
65 pub const Combined = combined_enum;
66
67 const conversion_map: [combined_enums]ConversionMap = conv_map_const;
68
69 pub fn originalType(value: @TypeOf(Combined)) type {
70 const int_rep: u8 = @intFromEnum(value);
71
72 for (conversion_map) |map| {
73 if (map.start <= int_rep and int_rep <= map.end) return map.T;
74 }
75 }
76 };
77}
78
79test {
80 const testing = @import("std").testing;
81 testing.refAllDeclsRecursive(@This());
82}