1#include "src/pw_alloc.h"
  2#include "src/types/struct_internal.h"
  3
  4[[nodiscard]] bool _pw_struct_alloc(PwValuePtr value)
  5{
  6    PwType* type = _pw_types[value->type_id];
  7
  8    // allocate memory
  9
 10    _PwStructData* struct_data = _pw_alloc(value->type_id, type->total_struct_size, true);
 11    if (!struct_data) {
 12        return false;
 13    }
 14    value->struct_data = (uint8_t*) struct_data;
 15    value->struct_offset = type->struct_offsets[0];
 16
 17    _pw_atomic_store(&struct_data->refcount, 1);
 18    _pw_atomic_store(&struct_data->itercount, 0);
 19    return true;
 20}
 21
 22static bool struct_create(PwMethod_Basic_create* mthis, PwValuePtr result, PwCtorArgs* ctor_args)
 23{
 24    return _pw_struct_alloc(result);
 25}
 26
 27static bool struct_destroy(PwMethod_Basic_destroy* mthis, PwValuePtr self, _PwCompoundChain* tail)
 28{
 29    PwValuePtr value_seen = _pw_on_chain(self, tail);
 30    if (value_seen) {
 31        return true;
 32    }
 33    _pw_free(self->type_id, (void**) &self->struct_data, pw_typeof(self)->total_struct_size);
 34    return true;
 35}
 36
 37static bool struct_clone(PwMethod_Basic_clone* mthis, PwValuePtr self)
 38{
 39    _PwStructData* struct_data = (_PwStructData*) self->struct_data;
 40    _pw_atomic_add(&struct_data->refcount, 1);
 41    return true;
 42}
 43
 44static bool struct_decref(PwMethod_Basic_decref* mthis, PwValuePtr self)
 45{
 46    _PwStructData* struct_data = (_PwStructData*) self->struct_data;
 47    return _pw_atomic_sub(&struct_data->refcount, 1) != 1;
 48}
 49
 50static bool struct_hash(PwMethod_Basic_hash* mthis, PwValuePtr self, PwHashContext* ctx, _PwCompoundChain* tail)
 51{
 52    _pw_hash_uint64(ctx, self->type_id);
 53    _pw_hash_uint64(ctx, (uint64_t) self->struct_data);
 54    return true;
 55}
 56
 57static bool struct_deepcopy(PwMethod_Basic_deepcopy* mthis, PwValuePtr self, PwValuePtr result, _PwCompoundChain* tail)
 58{
 59    pw_set_status(PwStatus(PweNotImplemented));
 60    return false;
 61}
 62
 63static bool struct_dump(PwMethod_Basic_dump* mthis, PwValuePtr self, FILE* fp, int indent, _PwCompoundChain* tail)
 64{
 65    _pw_print_indent(fp, indent);
 66    _pw_print_type(fp, self);
 67
 68    _PwStructData* struct_data = (_PwStructData*) self->struct_data;
 69
 70    if (struct_data) {
 71        fprintf(fp, "; data=%p refcount=%u itercount=%u\n",
 72                (void*) struct_data, _pw_atomic_load(&struct_data->refcount), _pw_atomic_load(&struct_data->itercount));
 73    } else {
 74        fputs("; data=NULL\n", fp);
 75    }
 76    return true;
 77}
 78
 79static bool struct_to_string(PwMethod_Basic_to_string* mthis, PwValuePtr self, PwValuePtr result, _PwCompoundChain* tail)
 80{
 81    pw_set_status(PwStatus(PweNotImplemented));
 82    return false;
 83}
 84
 85static bool struct_is_true(PwMethod_Basic_is_true* mthis, PwValuePtr self, _PwCompoundChain* tail)
 86{
 87    return false;
 88}
 89
 90static bool struct_equal(PwMethod_Basic_equal* mthis, PwValuePtr self, PwValuePtr other, _PwCompoundChain* tail)
 91{
 92    if (other->type_id != PwTypeId_Struct) {
 93        // there's no point to compare with base types; types must match exactly
 94        return false;
 95    }
 96    // basic Structs are empty and empty always equals empty
 97    return true;
 98}
 99
100#define struct_is_immutable  nullptr
101#define struct_iter_children nullptr
102
103PwInterface_Basic _pw_struct_basic_interface = {
104#define X(name, ...) .name = { .func = struct_##name } __VA_OPT__(,)
105    PW_BASIC_INTERFACE_METHODS
106#undef X
107};