1 // Metamethods for enums
6 #include "metamethods.h"
11 CONSTFUNC static ptrdiff_t value_offset(const TypeInfo_t *type) {
12 ptrdiff_t offset = sizeof(int32_t);
13 for (int i = 0; i < type->EnumInfo.num_tags; i++) {
14 if (type->EnumInfo.tags[i].type) offset = MAX(offset, type->EnumInfo.tags[i].type->align);
19 PUREFUNC public uint64_t Enum$hash(const void *obj, const TypeInfo_t *type) {
20 int32_t tag = *(int32_t *)obj;
21 uint32_t components[2] = {(uint32_t)tag, 0};
23 const TypeInfo_t *value = type->EnumInfo.tags[tag - 1].type;
24 if (value && value->size > 0) {
25 components[1] = generic_hash(obj + value_offset(type), value);
27 return siphash24((void *)components, sizeof(components));
30 PUREFUNC public int32_t Enum$compare(const void *x, const void *y, const TypeInfo_t *type) {
33 int32_t x_tag = *(int32_t *)x;
34 int32_t y_tag = *(int32_t *)y;
35 if (x_tag != y_tag) return x_tag > y_tag ? 1 : -1;
37 const TypeInfo_t *value = type->EnumInfo.tags[x_tag - 1].type;
38 if (value && value->size > 0) {
39 ptrdiff_t byte_offset = value_offset(type);
40 return generic_compare(x + byte_offset, y + byte_offset, value);
45 PUREFUNC public bool Enum$equal(const void *x, const void *y, const TypeInfo_t *type) {
46 if (x == y) return true;
48 int32_t x_tag = *(int32_t *)x;
49 int32_t y_tag = *(int32_t *)y;
50 if (x_tag != y_tag) return false;
52 const TypeInfo_t *value = type->EnumInfo.tags[x_tag - 1].type;
53 if (value && value->size > 0) {
54 ptrdiff_t byte_offset = value_offset(type);
55 return generic_equal(x + byte_offset, y + byte_offset, value);
61 Text_t Enum$as_text(const void *obj, bool colorize, const TypeInfo_t *type) {
62 if (!obj) return Text$from_str(type->EnumInfo.name);
64 int32_t tag = *(int32_t *)obj;
65 NamedType_t value = type->EnumInfo.tags[tag - 1];
66 if (!value.type || value.type->size == 0) {
67 Text_t text = Text$from_str(value.name);
68 return colorize ? Text$concat(Text("\x1b[1m"), text, Text("\x1b[m")) : text;
71 return generic_as_text(obj + value_offset(type), colorize, value.type);
74 PUREFUNC public bool Enum$is_none(const void *x, const TypeInfo_t *info) {
76 return *(int32_t *)x == 0;
80 void Enum$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) {
81 int32_t tag = *(int32_t *)obj;
82 Int32$serialize(&tag, out, pointers, &Int32$info);
84 NamedType_t value = type->EnumInfo.tags[tag - 1];
85 if (value.type && value.type->size > 0) {
86 _serialize(obj + value_offset(type), out, pointers, value.type);
91 void Enum$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type) {
93 Int32$deserialize(in, &tag, pointers, &Int32$info);
94 *(int32_t *)outval = tag;
96 NamedType_t value = type->EnumInfo.tags[tag - 1];
97 if (value.type && value.type->size > 0) {
98 _deserialize(in, outval + value_offset(type), pointers, value.type);