// @Cleanup: Put a better version of this into the standard library. enum_names :: ($t: Type) -> [] string { info := type_info(t); assert(info.type == .ENUM); return info.names; } enum_values_as_s64 :: ($T: Type) -> [] s64 { info := type_info(T); assert(info.type == .ENUM); return info.values; } enum_values_as_enum :: ($T: Type) -> [] T { // This is likely to be renamed "enum_values" eventually. info := type_info(T); assert(info.type == .ENUM); result: [..] T; result.allocator = temp; array_reserve(*result, info.values.count); for info.values array_add(*result, cast,no_check(T) it); return result; } enum_highest_value :: ($t: Type) -> s64 { _, high := enum_range_given_info(type_info(t)); return high; } enum_lowest_value :: ($t: Type) -> s64 { low, _ := enum_range_given_info(type_info(t)); return low; } enum_range :: ($t: Type) -> (low: s64, high: s64) { low, high := enum_range_given_info(type_info(t)); return low, high; } enum_range_given_info :: (info: *Type_Info_Enum) -> (low: s64, high: s64) { // @Cleanup: A safe version of this will return type_of(T.loose) if info.values.count == 0 return 0, 0; low := cast(s64) info.values[0]; high := low; for info.values { low = min(low, it); high = max(high, it); } return low, high; } enum_count :: ($T: Type) -> (count: s32) #expand { return cast(s32)type_info(T).values.count; } @Utility enum_increment :: (e: *$T) { e.* += 1; if cast(s64)e.* > enum_highest_value(T) { e.* = xx enum_lowest_value(T); } }