From 7e5759ed03eb0375d7ac9723fbbca06a63509682 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 18 Sep 2024 14:52:39 -0700 Subject: [PATCH] finish first pass sketching out basic base-layer-defined codebase type info & serialization/deserialization path with basic pointer cases --- project.4coder | 2 +- src/base/base_meta.c | 295 ++++++++++++++++++++++++++++--------- src/base/base_meta.h | 73 +++++---- src/scratch/ryan_scratch.c | 59 ++++---- 4 files changed, 305 insertions(+), 124 deletions(-) diff --git a/project.4coder b/project.4coder index 767c54a9..888697b1 100644 --- a/project.4coder +++ b/project.4coder @@ -46,7 +46,7 @@ load_paths = commands = { //- rjf: fkey command slots (change locally but do not commit) - .f1 = { .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f1 = { .win = "build ryan_scratch", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --auto_step && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/base/base_meta.c b/src/base/base_meta.c index 90e18c99..b9b8f8a6 100644 --- a/src/base/base_meta.c +++ b/src/base/base_meta.c @@ -8,7 +8,7 @@ internal Member * member_from_name(Type *type, String8 name) { Member *member = &member_nil; - if(type->members != 0) + if(type->members != 0 && name.size != 0) { for(U64 idx = 0; idx < type->count; idx += 1) { @@ -26,7 +26,7 @@ member_from_name(Type *type, String8 name) //~ rjf: Type Info * Instance Operations internal String8 -serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializeParams *params) +serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) { Temp scratch = scratch_begin(&arena, 1); String8List strings = {0}; @@ -37,29 +37,30 @@ serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializePar { Task *next; Type *type; - void *ptr; U64 count; + U8 *src; Type *containing_type; - void *containing_ptr; + U8 *containing_ptr; + B32 is_post_header; }; - Task start_task = {0, type, ptr, 1}; + Task start_task = {0, type, 1, data.str}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) { switch(t->type->kind) { - //- rjf: leaf serialiation -> just write the data directly + //- rjf: leaf -> just copy the data directly default: if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) { - str8_serial_push_string(scratch.arena, &strings, str8((U8 *)t->ptr, type_leaves[t->type->kind].size*t->count)); + str8_serial_push_string(scratch.arena, &strings, str8(t->src, t->type->size*t->count)); }break; - //- rjf: pointers -> try to interpret/understand pointer & write, otherwise skip + //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip case TypeKind_Ptr: { - // rjf: gather info about pointer references of this type + // rjf: unpack info about this pointer TypeSerializePtrRefInfo *ptr_ref_info = 0; for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) { @@ -70,60 +71,57 @@ serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializePar } } - // rjf: read ptr value - void *ptr_value = 0; - MemoryCopy(&ptr_value, t->ptr, sizeof(ptr_value)); - // rjf: indexification -> subtract base, divide direct size, write index if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) { - U64 ptr_offsetified = (U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base; - U64 ptr_indexified = ptr_offsetified / t->type->direct->size; - str8_serial_push_struct(scratch.arena, &strings, &ptr_indexified); + U64 ptr_value = 0; + MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); + U64 ptr_write_value = ((U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base)/t->type->direct->size); + str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); } - // rjf: explicit identification -> descend to ID member at destination, write that - else if(ptr_ref_info != 0 && ptr_ref_info->id_member.size != 0) + // rjf: offsetification -> subtract base, write offsets + else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) { - Member *member = member_from_name(t->type->direct, ptr_ref_info->id_member); - if(member != &member_nil) - { - Task *task = push_array(scratch.arena, Task, 1); - task->type = member->type; - task->ptr = ((U8 *)ptr_value) + member->value; - task->count = 1; - task->containing_type = t->type->direct; - task->containing_ptr = ptr_value; - SLLQueuePush(first_task, last_task, task); - } + U64 ptr_value = 0; + MemoryCopy(&ptr_value, t->src, sizeof(ptr_value)); + U64 ptr_write_value = (U64)((U8 *)ptr_value - (U8 *)ptr_ref_info->offsetify_base); + str8_serial_push_struct(scratch.arena, &strings, &ptr_write_value); } - // rjf: count-delimited pointers -> read count from member in containing type, - // descend & write destination that way - else if(t->type->count_delimiter_name.size != 0 && t->containing_type != 0) - { - Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); - if(count_member != &member_nil) - { - U64 count = 0; - MemoryCopy(&count, (U8 *)t->containing_ptr + count_member->value, count_member->type->size); - Task *task = push_array(scratch.arena, Task, 1); - task->type = t->type->direct; - task->ptr = ptr_value; - task->count = count; - task->containing_type = t->containing_type; - task->containing_ptr = t->containing_ptr; - SLLQueuePush(first_task, last_task, task); - } - } - - // rjf: any other nonzero pointer -> descend to pointer destination. trust usage code - else if(ptr_value != 0) + // rjf: size-by-member (pre-header): still potentially dependent on other members which + // delimit our size, so push a new post-header task for pointer. + else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) { Task *task = push_array(scratch.arena, Task, 1); - task->type = t->type->direct; - task->ptr = ptr_value; - task->count = 1; + task->type = t->type; + task->count = t->count; + task->src = t->src; + task->containing_type = t->containing_type; + task->containing_ptr = t->containing_ptr; + task->is_post_header = 1; + SLLQueuePush(first_task, last_task, task); + } + + // rjf: size-by-member (post-header): all flat parts of containing struct have been + // iterated, so now we can read the size, & descend to new task to read pointer + // destination contents + else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) + { + // rjf: determine count of this pointer + U64 count = 0; + { + Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); + MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); + } + + // rjf: push task + Task *task = push_array(scratch.arena, Task, 1); + task->type = t->type->direct; + task->count = count; + task->src = *(void **)t->src; + task->containing_type = t->containing_type; + task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); } }break; @@ -132,9 +130,175 @@ serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializePar case TypeKind_Array: { Task *task = push_array(scratch.arena, Task, 1); - task->type = t->type->direct; - task->ptr = t->ptr; - task->count = t->type->count; + task->type = t->type->direct; + task->count = t->type->count; + task->src = t->src; + task->containing_type = t->containing_type; + task->containing_ptr = t->containing_ptr; + SLLQueuePush(first_task, last_task, task); + }break; + + //- rjf: struct -> descend to members + case TypeKind_Struct: + { + U64 off = 0; + for(U64 idx = 0; idx < t->count; idx += 1) + { + for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1) + { + if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize) + { + continue; + } + Task *task = push_array(scratch.arena, Task, 1); + task->type = t->type->members[member_idx].type; + task->count = 1; + task->src = t->src + t->type->members[member_idx].value; + task->containing_type = t->type; + task->containing_ptr = t->src; + SLLQueuePush(first_task, last_task, task); + } + } + }break; + + //- rjf: enum -> descend to basic type interpretation + case TypeKind_Enum: + { + Task *task = push_array(scratch.arena, Task, 1); + task->type = t->type->direct; + task->count = t->count; + task->src = t->src; + task->containing_type = t->containing_type; + task->containing_ptr = t->containing_ptr; + SLLQueuePush(first_task, last_task, task); + }break; + } + } + } + String8 result = str8_serial_end(arena, &strings); + scratch_end(scratch); + return result; +} + +internal String8 +deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params) +{ + String8 result = {0}; + result.size = type->size; + result.str = push_array(arena, U8, result.size); + { + Temp scratch = scratch_begin(&arena, 1); + typedef struct Task Task; + struct Task + { + Task *next; + Type *type; + U64 count; + U8 *dst; + Type *containing_type; + U8 *containing_ptr; + B32 is_post_header; + }; + U64 read_off = 0; + Task start_task = {0, type, 1, result.str}; + Task *first_task = &start_task; + Task *last_task = first_task; + for(Task *t = first_task; t != 0; t = t->next) + { + U8 *t_src = data.str + read_off; + switch(t->type->kind) + { + //- rjf: leaf -> copy the data directly + default: + if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf) + { + MemoryCopy(t->dst, t_src, t->type->size*t->count); + read_off += t->type->size*t->count; + }break; + + //- rjf: pointers -> try to interpret/understand pointer & read/write, otherwise skip + case TypeKind_Ptr: + { + // rjf: unpack info about this pointer + TypeSerializePtrRefInfo *ptr_ref_info = 0; + for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1) + { + if(params->ptr_ref_infos[idx].type == t->type->direct) + { + ptr_ref_info = ¶ms->ptr_ref_infos[idx]; + break; + } + } + + // rjf: indexification -> add base, multiply direct size + if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0) + { + U64 ptr_value = 0; + MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); + U64 ptr_write_value = (ptr_value + (U64)ptr_ref_info->indexify_base) * t->type->direct->size; + MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); + read_off += sizeof(ptr_value); + } + + // rjf: offsetification -> subtract base, write offsets + else if(ptr_ref_info != 0 && ptr_ref_info->offsetify_base != 0) + { + U64 ptr_value = 0; + MemoryCopy(&ptr_value, t_src, sizeof(ptr_value)); + U64 ptr_write_value = ptr_value + (U64)ptr_ref_info->offsetify_base; + MemoryCopy(t->dst, &ptr_write_value, sizeof(ptr_write_value)); + read_off += sizeof(ptr_value); + } + + // rjf: size-by-member (pre-header): still potentially dependent on other members which + // delimit our size, so push a new post-header task for pointer. + else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header) + { + Task *task = push_array(scratch.arena, Task, 1); + task->type = t->type; + task->count = t->count; + task->dst = t->dst; + task->containing_type = t->containing_type; + task->containing_ptr = t->containing_ptr; + task->is_post_header = 1; + SLLQueuePush(first_task, last_task, task); + } + + // rjf: size-by-member (post-header): all flat parts of containing struct have been + // iterated, so now we can read the size, & descend to new task to read pointer + // destination contents + else if(t->type->count_delimiter_name.size != 0 && t->is_post_header) + { + // rjf: determine count of this pointer + U64 count = 0; + { + Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name); + MemoryCopy(&count, t->containing_ptr + count_member->value, count_member->type->size); + } + + // rjf: allocate buffer for pointer destination; write address into pointer value slot + U64 ptr_dest_buffer_size = count*t->type->direct->size; + U8 *ptr_dest_buffer = push_array(arena, U8, ptr_dest_buffer_size); + MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer)); + + // rjf: push task + Task *task = push_array(scratch.arena, Task, 1); + task->type = t->type->direct; + task->count = count; + task->dst = ptr_dest_buffer; + task->containing_type = t->containing_type; + task->containing_ptr = t->containing_ptr; + SLLQueuePush(first_task, last_task, task); + } + }break; + + //- rjf: arrays -> descend to underlying type, + count + case TypeKind_Array: + { + Task *task = push_array(scratch.arena, Task, 1); + task->type = t->type->direct; + task->count = t->type->count; + task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); @@ -153,10 +317,10 @@ serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializePar } Task *task = push_array(scratch.arena, Task, 1); task->type = t->type->members[member_idx].type; - task->ptr = (U8 *)t->ptr + t->type->size*idx + t->type->members[member_idx].value; task->count = 1; + task->dst = t->dst + t->type->members[member_idx].value; task->containing_type = t->type; - task->containing_ptr = t->ptr; + task->containing_ptr = t->dst; SLLQueuePush(first_task, last_task, task); } } @@ -166,23 +330,16 @@ serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializePar case TypeKind_Enum: { Task *task = push_array(scratch.arena, Task, 1); - task->type = t->type->direct; - task->ptr = t->ptr; - task->count = t->count; + task->type = t->type->direct; + task->count = t->count; + task->dst = t->dst; task->containing_type = t->containing_type; task->containing_ptr = t->containing_ptr; SLLQueuePush(first_task, last_task, task); }break; } } + scratch_end(scratch); } - String8 result = str8_serial_end(scratch.arena, &strings); - scratch_end(scratch); return result; } - -internal void * -data_from_typed_serialized(Arena *arena, Type *type, String8 string, TypeSerializeParams *params) -{ - -} diff --git a/src/base/base_meta.h b/src/base/base_meta.h index c43df323..f27533b5 100644 --- a/src/base/base_meta.h +++ b/src/base/base_meta.h @@ -138,9 +138,10 @@ struct Type typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo; struct TypeSerializePtrRefInfo { - Type *type; // pointers to this - void *indexify_base; // can be indexified using this - String8 id_member; // or ID'd via this member of the pointed-to-instance + Type *type; // pointers to this + void *indexify_base; // can be indexified using this + void *offsetify_base; // can be offsetified using this + void *nil_ptr; // is terminal if matching 0 or this }; typedef struct TypeSerializeParams TypeSerializeParams; @@ -150,42 +151,62 @@ struct TypeSerializeParams U64 ptr_ref_infos_count; }; +//////////////////////////////// +//~ rjf: Type Name -> Type Info + +#define type(T) &(T##__type) + //////////////////////////////// //~ rjf: Globals -read_only global Type type_leaves[] = +read_only global Type type_nil = {TypeKind_Null, 0, 0, &type_nil}; +read_only global Type void__type = {TypeKind_Void, 0, 0, &type_nil, str8_lit_comp("void")}; +read_only global Type U8__type = {TypeKind_U8, 0, sizeof(U8), &type_nil, str8_lit_comp("U8")}; +read_only global Type U16__type = {TypeKind_U16, 0, sizeof(U16), &type_nil, str8_lit_comp("U16")}; +read_only global Type U32__type = {TypeKind_U32, 0, sizeof(U32), &type_nil, str8_lit_comp("U32")}; +read_only global Type U64__type = {TypeKind_U64, 0, sizeof(U64), &type_nil, str8_lit_comp("U64")}; +read_only global Type S8__type = {TypeKind_S8, 0, sizeof(S8), &type_nil, str8_lit_comp("S8")}; +read_only global Type S16__type = {TypeKind_S16, 0, sizeof(S16), &type_nil, str8_lit_comp("S16")}; +read_only global Type S32__type = {TypeKind_S32, 0, sizeof(S32), &type_nil, str8_lit_comp("S32")}; +read_only global Type S64__type = {TypeKind_S64, 0, sizeof(S64), &type_nil, str8_lit_comp("S64")}; +read_only global Type B8__type = {TypeKind_B8, 0, sizeof(B8), &type_nil, str8_lit_comp("B8")}; +read_only global Type B16__type = {TypeKind_B16, 0, sizeof(B16), &type_nil, str8_lit_comp("B16")}; +read_only global Type B32__type = {TypeKind_B32, 0, sizeof(B32), &type_nil, str8_lit_comp("B32")}; +read_only global Type B64__type = {TypeKind_B64, 0, sizeof(B64), &type_nil, str8_lit_comp("B64")}; +read_only global Type F32__type = {TypeKind_F32, 0, sizeof(F32), &type_nil, str8_lit_comp("F32")}; +read_only global Type F64__type = {TypeKind_F64, 0, sizeof(F64), &type_nil, str8_lit_comp("F64")}; +read_only global Type *type_leaves[] = { - {TypeKind_Null, 0, 0, &type_leaves[0], str8_lit_comp("null")}, - {TypeKind_Void, 0, 0, &type_leaves[0], str8_lit_comp("void")}, - {TypeKind_U8, 0, sizeof(U8), &type_leaves[0], str8_lit_comp("U8")}, - {TypeKind_U16, 0, sizeof(U16), &type_leaves[0], str8_lit_comp("U16")}, - {TypeKind_U32, 0, sizeof(U32), &type_leaves[0], str8_lit_comp("U32")}, - {TypeKind_U64, 0, sizeof(U64), &type_leaves[0], str8_lit_comp("U64")}, - {TypeKind_S8, 0, sizeof(S8), &type_leaves[0], str8_lit_comp("S8")}, - {TypeKind_S16, 0, sizeof(S16), &type_leaves[0], str8_lit_comp("S16")}, - {TypeKind_S32, 0, sizeof(S32), &type_leaves[0], str8_lit_comp("S32")}, - {TypeKind_S64, 0, sizeof(S64), &type_leaves[0], str8_lit_comp("S64")}, - {TypeKind_B8, 0, sizeof(B8), &type_leaves[0], str8_lit_comp("B8")}, - {TypeKind_B16, 0, sizeof(B16), &type_leaves[0], str8_lit_comp("B16")}, - {TypeKind_B32, 0, sizeof(B32), &type_leaves[0], str8_lit_comp("B32")}, - {TypeKind_B64, 0, sizeof(B64), &type_leaves[0], str8_lit_comp("B64")}, - {TypeKind_F32, 0, sizeof(F32), &type_leaves[0], str8_lit_comp("F32")}, - {TypeKind_F64, 0, sizeof(F64), &type_leaves[0], str8_lit_comp("F64")}, + &type_nil, + type(void), + type(U8), + type(U16), + type(U32), + type(U64), + type(S8), + type(S16), + type(S32), + type(S64), + type(B8), + type(B16), + type(B32), + type(B64), + type(F32), + type(F64), }; -read_only global Member member_nil = {{0}, &type_leaves[0]}; +read_only global Member member_nil = {{0}, &type_nil}; //////////////////////////////// //~ rjf: Type Info Lookups -#define type(T) &(T##__type) internal Member *member_from_name(Type *type, String8 name); //////////////////////////////// //~ rjf: Type Info * Instance Operations -internal String8 serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializeParams *params); -internal void *data_from_typed_serialized(Arena *arena, Type *type, String8 string, TypeSerializeParams *params); -#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), (ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}) -#define struct_from_serialized(arena, T, string, ...) (T *)data_from_typed_serialized((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}) +internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); +internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params); +#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}) +#define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str #endif // BASE_META_H diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index c707e363..29b85e44 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -54,12 +54,12 @@ struct FooBar //- -Type String8__str_ptr_type = {TypeKind_Ptr, 0, sizeof(void *), &type_leaves[TypeKind_U8], {0}, str8_lit_comp("size")}; +Type String8__str_ptr_type = {TypeKind_Ptr, 0, sizeof(void *), type(U8), {0}, str8_lit_comp("size")}; Member String8__members[] = { - {str8_lit_comp("str"), &String8__str_ptr_type, OffsetOf(String8, str)}, - {str8_lit_comp("size"), &type_leaves[TypeKind_U64], OffsetOf(String8, size)}, + {str8_lit_comp("str"), &String8__str_ptr_type, OffsetOf(String8, str)}, + {str8_lit_comp("size"), type(U64), OffsetOf(String8, size)}, }; Type String8__type = @@ -67,7 +67,7 @@ Type String8__type = TypeKind_Struct, 0, sizeof(String8), - &type_leaves[0], + &type_nil, str8_lit_comp("String8"), {0}, ArrayCount(String8__members), @@ -90,7 +90,7 @@ Type String8Node__type = TypeKind_Struct, 0, sizeof(String8Node), - &type_leaves[0], + &type_nil, str8_lit_comp("String8Node"), {0}, ArrayCount(String8Node__members), @@ -103,8 +103,8 @@ Member String8List__members[] = { {str8_lit_comp("first"), &String8Node__ptr_type, OffsetOf(String8List, first)}, {str8_lit_comp("last"), &String8Node__ptr_type, OffsetOf(String8List, last), MemberFlag_DoNotSerialize}, - {str8_lit_comp("node_count"), &type_leaves[TypeKind_U64], OffsetOf(String8List, node_count)}, - {str8_lit_comp("total_size"), &type_leaves[TypeKind_U64], OffsetOf(String8List, total_size)}, + {str8_lit_comp("node_count"), type(U64), OffsetOf(String8List, node_count)}, + {str8_lit_comp("total_size"), type(U64), OffsetOf(String8List, total_size)}, }; Type String8List__type = @@ -112,7 +112,7 @@ Type String8List__type = TypeKind_Struct, 0, sizeof(String8List), - &type_leaves[0], + &type_nil, str8_lit_comp("String8List"), {0}, ArrayCount(String8List__members), @@ -123,10 +123,10 @@ Type String8List__type = Member FooBar__members[] = { - {str8_lit_comp("x"), &type_leaves[TypeKind_U64], OffsetOf(FooBar, x)}, - {str8_lit_comp("y"), &type_leaves[TypeKind_U64], OffsetOf(FooBar, y)}, - {str8_lit_comp("z"), &type_leaves[TypeKind_U64], OffsetOf(FooBar, z)}, - {str8_lit_comp("name"), type(String8), OffsetOf(FooBar, name)}, + {str8_lit_comp("x"), type(U64), OffsetOf(FooBar, x)}, + {str8_lit_comp("y"), type(U64), OffsetOf(FooBar, y)}, + {str8_lit_comp("z"), type(U64), OffsetOf(FooBar, z)}, + {str8_lit_comp("name"), type(String8), OffsetOf(FooBar, name)}, }; Type FooBar__type = @@ -134,7 +134,7 @@ Type FooBar__type = TypeKind_Struct, 0, sizeof(FooBar), - &type_leaves[0], + &type_nil, str8_lit_comp("FooBar"), {0}, ArrayCount(FooBar__members), @@ -146,23 +146,26 @@ entry_point(CmdLine *cmdline) { Arena *arena = arena_alloc(); - String8List strs = {0}; - str8_list_pushf(arena, &strs, "foobar: %i", 123); - str8_list_pushf(arena, &strs, "xyzxyzxyz"); - str8_list_pushf(arena, &strs, "abc abc abc"); - str8_list_pushf(arena, &strs, "123"); - str8_list_pushf(arena, &strs, "456"); - str8_list_pushf(arena, &strs, "789"); - str8_list_pushf(arena, &strs, "111"); - str8_list_pushf(arena, &strs, "222"); - str8_list_pushf(arena, &strs, "333"); - String8 strs_serialized = serialized_from_struct(arena, String8List, &strs); + FooBar foobar_in = {1, 2, 3, str8_lit("foobar 123 hello world")}; + String8 foobar_srlz = serialized_from_struct(arena, FooBar, &foobar_in); + FooBar foobar_out = *struct_from_serialized(arena, FooBar, foobar_srlz); - String8 test_name = str8_lit("foobar 123"); - String8 test_name_serialized = serialized_from_struct(arena, String8, &test_name); + String8List strs_in = {0}; + str8_list_pushf(arena, &strs_in, "foobar: %i", 123); + str8_list_pushf(arena, &strs_in, "xyzxyzxyz"); + str8_list_pushf(arena, &strs_in, "abc abc abc"); + str8_list_pushf(arena, &strs_in, "123"); + str8_list_pushf(arena, &strs_in, "456"); + str8_list_pushf(arena, &strs_in, "789"); + str8_list_pushf(arena, &strs_in, "111"); + str8_list_pushf(arena, &strs_in, "222"); + str8_list_pushf(arena, &strs_in, "333"); + String8 strs_serialized = serialized_from_struct(arena, String8List, &strs_in); + String8List strs_out = *struct_from_serialized(arena, String8List, strs_serialized); - FooBar foobar = {1, 2, 3, str8_lit("foobar 123 hello world")}; - String8 foobar_serialized = serialized_from_struct(arena, FooBar, &foobar); + String8 test_name_in = str8_lit("foobar 123"); + String8 test_name_srlz = serialized_from_struct(arena, String8, &test_name_in); + String8 test_name_out = *struct_from_serialized(arena, String8, test_name_srlz); int x = 0;