A SpaceTraders Agent
at main 2.3 kB view raw
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}