Skip to content
Flecs v4.1
reflection/custom_serializer

  • C

    View on GitHub

    1#include <custom_serializer.h>
    2#include <stdio.h>
    3#include <inttypes.h>
    4
    5// This example demonstrates how to create a serializer for a custom format.
    6
    7static int indent = 0;
    8
    9#define printIndented(...)\
    10 printf("\n%*s", indent * 2, ""); printf(__VA_ARGS__)
    11
    12void serializeOps(ecs_world_t *world, ecs_meta_op_t *ops,
    13 int32_t op_count, const void *ptr);
    14
    15// Serialize a pointer of a specified type.
    16int serialize(ecs_world_t *world, ecs_entity_t type, const void *ptr) {
    17 // The TypeSerializer component contains a vector of instructions that tells
    18 // us how to serialize the type.
    19 const EcsTypeSerializer *s = ecs_get(world, type, EcsTypeSerializer);
    20 if (!s) {
    21 printf("type does not have reflection data\n");
    22 return -1;
    23 }
    24
    25 serializeOps(world, ecs_vec_first(&s->ops), ecs_vec_count(&s->ops), ptr);
    26
    27 return 0;
    28}
    29
    30// Serialize contents of struct or collection scope
    31void serializeScope(ecs_world_t *world, ecs_meta_op_t *ops, const void *ptr) {
    32 // A scope starts with a Push and ends with a Pop, so trim the first and
    33 // last instruction before forwarding.
    34 serializeOps(world, ops + 1, ops->op_count - 2, ptr);
    35}
    36
    37// Serialize a struct scope
    38void serializeStruct(ecs_world_t *world, ecs_meta_op_t *ops,
    39 const void *ptr)
    40{
    41 printf("{");
    42 indent ++;
    43
    44 serializeScope(world, ops, ptr);
    45
    46 indent --;
    47 printIndented("}");
    48}
    49
    50// Serialize an array scope
    51void serializeArray(ecs_world_t *world, ecs_meta_op_t *ops,
    52 int32_t elem_count, const void *ptr)
    53{
    54 printf("[");
    55
    56 // Iterate elements of the array. Skip the first and last instruction
    57 // since they are PushStruct and Pop.
    58 for (int i = 0; i < elem_count; i ++) {
    59 if (i) {
    60 printf(", ");
    61 }
    62
    63 serializeScope(world, ops, ptr);
    64
    65 ptr = ECS_OFFSET(ptr, ops->elem_size);
    66 }
    67
    68 printf("]");
    69}
    70
    71// Serialize a vector scope
    72void serializeVector(ecs_world_t *world, ecs_meta_op_t *ops,
    73 const void *ptr)
    74{
    75 const ecs_vec_t *vec = ptr;
    76 serializeArray(world, ops, vec->count, vec->array);
    77}
    78
    79// Serialize enum
    80void serializeEnum(ecs_meta_op_t *op, const void *ptr)
    81{
    82 ecs_map_key_t value;
    84
    85 if (kind == EcsOpU8 || kind == EcsOpI8) {
    86 value = *(const uint8_t*)ptr;
    87 } else if (kind == EcsOpU16 || kind == EcsOpI16) {
    88 value = *(const uint16_t*)ptr;
    89 } else if (kind == EcsOpU32 || kind == EcsOpI32) {
    90 value = *(const uint32_t*)ptr;
    91 } else if (kind == EcsOpUPtr || kind == EcsOpIPtr) {
    92 value = *(const uintptr_t*)ptr;
    93 } else if (kind == EcsOpU64 || kind == EcsOpI64) {
    94 value = *(const uint64_t*)ptr;
    95 } else {
    96 printf("<<invalid underlying enum type>>");
    97 return;
    98 }
    99
    100 ecs_enum_constant_t *c = ecs_map_get_deref(op->is.constants,
    101 ecs_enum_constant_t, value);
    102 printf("%s", c->name);
    103}
    104
    105// Iterate over instruction array
    106void serializeOps(ecs_world_t *world, ecs_meta_op_t *ops, int32_t op_count,
    107 const void *base)
    108{
    109 for (int i = 0; i < op_count; i ++) {
    110 ecs_meta_op_t *op = &ops[i];
    111
    112 // Member name
    113 if (op->name) {
    114 if (i) {
    115 printf(",");
    116 }
    117
    118 printIndented("%s: ", op->name);
    119 }
    120
    121 // Get pointer for current field
    122 void *ptr = ECS_OFFSET(base, op->offset);
    123
    124 switch(op->kind) {
    125 // Instructions that forward to a type scope, like a (nested) struct or
    126 // collection
    127 case EcsOpPushStruct:
    128 serializeStruct(world, op, ptr);
    129 break;
    130 case EcsOpPushArray:
    131 serializeArray(world, op, ecs_meta_op_get_elem_count(ops, ptr), ptr);
    132 break;
    133 case EcsOpPushVector:
    134 serializeVector(world, op, ptr);
    135 break;
    136
    137 case EcsOpPushMap:
    138 break;
    139
    140 // Value types hold a value of a type that is determined at runtime.
    141 // Serializing a value requires looking up the reflection data for the
    142 // stored type. For an example, see src/addons/script/serialize.c.
    143 case EcsOpPushValue:
    144 break;
    145
    146 // Opaque types have in-memory representations that are opaque to
    147 // the reflection framework and cannot be serialized by just taking
    148 // a pointer + an offset. See src/addons/script/serialize.c for an
    149 // example of how to handle opaque types.
    151 case EcsOpOpaqueArray:
    153 case EcsOpOpaqueValue:
    154 break;
    155
    156 // Forward to type. Used for members of array/vector types.
    157 case EcsOpForward:
    158 serialize(world, op->type, ptr);
    159 break;
    160
    161 // Serialize single values
    162 case EcsOpEnum:
    163 serializeEnum(op, ptr);
    164 break;
    165 case EcsOpBitmask:
    166 // Bitmask serialization requires iterating all the bits in a value
    167 // and looking up the corresponding constant. For an example, see
    168 // src/addons/script/serialize.c.
    169 break;
    170 case EcsOpBool:
    171 printf("%s", (*(const bool*)ptr) ? "true" : "false");
    172 break;
    173 case EcsOpChar:
    174 printf("'%c'", *(const char*)ptr);
    175 break;
    176 case EcsOpByte:
    177 case EcsOpU8:
    178 printf("%" PRIu8, *(const uint8_t*)ptr);
    179 break;
    180 case EcsOpU16:
    181 printf("%" PRIu16, *(const uint16_t*)ptr);
    182 break;
    183 case EcsOpU32:
    184 printf("%" PRIu32, *(const uint32_t*)ptr);
    185 break;
    186 case EcsOpU64:
    187 printf("%" PRIu64, *(const uint64_t*)ptr);
    188 break;
    189 case EcsOpI8:
    190 printf("%" PRIi8, *(const int8_t*)ptr);
    191 break;
    192 case EcsOpI16:
    193 printf("%" PRIi16, *(const int16_t*)ptr);
    194 break;
    195 case EcsOpI32:
    196 printf("%" PRIi32, *(const int32_t*)ptr);
    197 break;
    198 case EcsOpI64:
    199 printf("%" PRIi64, *(const int64_t*)ptr);
    200 break;
    201 case EcsOpF32:
    202 printf("%.2f", (double)*(const float*)ptr);
    203 break;
    204 case EcsOpF64:
    205 printf("%.2f", *(const double*)ptr);
    206 break;
    207 case EcsOpUPtr:
    208 printf("%" PRIuPTR, *(const uintptr_t*)ptr);
    209 break;
    210 case EcsOpIPtr:
    211 printf("%" PRIiPTR, *(const intptr_t*)ptr);
    212 break;
    213 case EcsOpString:
    214 printf("\"%s\"", *(const char**)ptr);
    215 break;
    216 case EcsOpEntity: {
    217 char *name = ecs_get_path(world, *(ecs_entity_t*)ptr);
    218 printf("%s\n", name);
    219 ecs_os_free(name);
    220 break;
    221 }
    222 case EcsOpId: {
    223 char *name = ecs_id_str(world, *(ecs_id_t*)ptr);
    224 printf("%s\n", name);
    225 ecs_os_free(name);
    226 break;
    227 }
    228 case EcsOpPop:
    229 case EcsOpScope:
    230 case EcsOpPrimitive:
    231 // Not serializable
    232 break;
    233 }
    234
    235 i += op->op_count - 1; // Skip over already processed instructions
    236 }
    237}
    238
    239// Some types to test the serializer with
    240
    241typedef struct {
    242 uint8_t red;
    243 uint8_t green;
    244 uint8_t blue;
    245} Rgb;
    246
    247typedef enum {
    248 Solid, Dashed
    249} StrokeKind;
    250
    251typedef struct {
    252 float x, y;
    253} Point;
    254
    255typedef struct {
    256 Rgb color;
    257 Rgb stroke_color;
    258 StrokeKind stroke_kind;
    259 ecs_vec_t points;
    260} Polygon;
    261
    262int main(int argc, char *argv[]) {
    263 ecs_world_t *world = ecs_init_w_args(argc, argv);
    264
    265 // We need to register reflection data for our types before we can use them
    266 // with the serializer code. We'll do it manually here, but for an easier
    267 // way to insert reflection data see the auto_* examples.
    268
    269 ECS_COMPONENT(world, Rgb);
    270 ECS_COMPONENT(world, StrokeKind);
    271 ECS_COMPONENT(world, Point);
    272 ECS_COMPONENT(world, Polygon);
    273
    274 ecs_struct(world, {
    275 .entity = ecs_id(Rgb),
    276 .members = {
    277 { .name = "r", .type = ecs_id(ecs_u8_t) },
    278 { .name = "g", .type = ecs_id(ecs_u8_t) },
    279 { .name = "b", .type = ecs_id(ecs_u8_t) },
    280 }
    281 });
    282
    283 ecs_enum(world, {
    284 .entity = ecs_id(StrokeKind),
    285 .constants = {
    286 { .name = "Solid", .value = Solid },
    287 { .name = "Dashed", .value = Dashed },
    288 }
    289 });
    290
    291 ecs_struct(world, {
    292 .entity = ecs_id(Point),
    293 .members = {
    294 { .name = "x", .type = ecs_id(ecs_f32_t) },
    295 { .name = "y", .type = ecs_id(ecs_f32_t) }
    296 }
    297 });
    298
    299 ecs_entity_t PointVector = ecs_vector(world, { .type = ecs_id(Point) });
    300
    301 ecs_struct(world, {
    302 .entity = ecs_id(Polygon),
    303 .members = {
    304 { .name = "color", .type = ecs_id(Rgb) },
    305 { .name = "stroke_color", .type = ecs_id(Rgb) },
    306 { .name = "stroke_kind", .type = ecs_id(StrokeKind) },
    307 { .name = "points", .type = PointVector }
    308 }
    309 });
    310
    311 // Create the value
    312 ecs_vec_t points;
    313 ecs_vec_init_t(NULL, &points, Point, 0);
    314 *ecs_vec_append_t(NULL, &points, Point) = (Point){0, 0};
    315 *ecs_vec_append_t(NULL, &points, Point) = (Point){1, 1};
    316 *ecs_vec_append_t(NULL, &points, Point) = (Point){-1, 1};
    317
    318 Polygon p = {
    319 .color = {0, 0, 255},
    320 .stroke_color = {255, 0, 0},
    321 .stroke_kind = Dashed,
    322 .points = points
    323 };
    324
    325 // Serialize value
    326 serialize(world, ecs_id(Polygon), &p);
    327 printf("\n");
    328
    329 // Free memory
    330 ecs_vec_fini_t(NULL, &points, Point);
    331
    332 ecs_fini(world);
    333
    334 // Output:
    335 // {
    336 // color: {
    337 // r: 0,
    338 // g: 0,
    339 // b: 255
    340 // },
    341 // stroke_color: {
    342 // r: 255,
    343 // g: 0,
    344 // b: 0
    345 // },
    346 // stroke_kind: Dashed,
    347 // points: [{
    348 // x: 0.00,
    349 // y: 0.00
    350 // }, {
    351 // x: 1.00,
    352 // y: 1.00
    353 // }, {
    354 // x: -1.00,
    355 // y: 1.00
    356 // }]
    357 // }
    358}
    FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
    Component ID for EcsDocDescription.
    ecs_meta_op_kind_t
    Serializer instruction opcodes.
    Definition meta.h:541
    uint8_t ecs_u8_t
    Built-in u8 type.
    Definition meta.h:98
    #define ecs_vector(world,...)
    Create a vector type.
    Definition meta.h:1765
    FLECS_API ecs_size_t ecs_meta_op_get_elem_count(const ecs_meta_op_t *op, const void *ptr)
    Get element count for array, vector or map operations.
    #define ecs_enum(world,...)
    Create an enum type.
    Definition meta.h:1753
    float ecs_f32_t
    Built-in f32 type.
    Definition meta.h:108
    #define ecs_struct(world,...)
    Create a struct type.
    Definition meta.h:1777
    @ EcsOpPrimitive
    Marks first constant that's a primitive.
    Definition meta.h:560
    @ EcsOpPushMap
    Push map.
    Definition meta.h:545
    @ EcsOpOpaqueArray
    Opaque array.
    Definition meta.h:550
    @ EcsOpOpaqueStruct
    Opaque struct.
    Definition meta.h:549
    @ EcsOpScope
    Marks last constant that can open or close a scope.
    Definition meta.h:554
    @ EcsOpPop
    Pop scope.
    Definition meta.h:547
    @ EcsOpPushVector
    Push vector.
    Definition meta.h:544
    @ EcsOpOpaqueVector
    Opaque vector.
    Definition meta.h:551
    @ EcsOpPushStruct
    Push struct.
    Definition meta.h:542
    @ EcsOpPushValue
    Push value.
    Definition meta.h:546
    @ EcsOpOpaqueValue
    Opaque value.
    Definition meta.h:556
    @ EcsOpPushArray
    Push array.
    Definition meta.h:543
    @ EcsOpForward
    Forward to type.
    Definition meta.h:552
    ecs_id_t ecs_entity_t
    An entity identifier.
    Definition flecs.h:395
    struct ecs_world_t ecs_world_t
    A world is the container for all ECS data and supporting features.
    Definition flecs.h:439
    uint64_t ecs_id_t
    IDs are the things that can be added to an entity.
    Definition flecs.h:388
    int(*)(const serializer *, const T *) serialize
    Type-safe variant of the serializer function.
    Definition opaque.hpp:26
    #define ECS_COMPONENT(world, id)
    Declare and define a component.
    Definition flecs_c.h:98
    #define ecs_get_path(world, child)
    Get path from root.
    Definition flecs_c.h:594
    #define ecs_get(world, entity, T)
    Get a component.
    Definition flecs_c.h:339
    char * ecs_id_str(const ecs_world_t *world, ecs_id_t component)
    Convert a component ID to a string.
    int ecs_fini(ecs_world_t *world)
    Delete a world.
    ecs_world_t * ecs_init_w_args(int argc, char *argv[])
    Create a new world with arguments.
    Component that stores the type serializer.
    Definition meta.h:603
    ecs_vec_t ops
    vector<ecs_meta_op_t>
    Definition meta.h:605
    Type that describes an enum constant.
    Definition meta.h:277
    const char * name
    Must be set when used with ecs_enum_desc_t.
    Definition meta.h:279
    Meta type serializer instruction data.
    Definition meta.h:584
    const char * name
    Name of value (only used for struct members).
    Definition meta.h:588
    ecs_meta_op_kind_t kind
    Instruction opcode.
    Definition meta.h:585
    ecs_entity_t type
    Type entity.
    Definition meta.h:592
    int16_t op_count
    Number of operations until next field or end.
    Definition meta.h:590
    ecs_meta_op_kind_t underlying_kind
    Underlying type kind (for enums).
    Definition meta.h:586
    ecs_size_t elem_size
    Element size (for PushArray or PushVector) and element count (for PopArray).
    Definition meta.h:589
    ecs_size_t offset
    Offset of current field.
    Definition meta.h:587

  • C++

    View on GitHub

    1#include <custom_serializer.h>
    2#include <iostream>
    3#include <vector>
    4#include <inttypes.h>
    5
    6// This example demonstrates how to create a serializer for a custom format.
    7
    8static int indent = 0;
    9
    10#define printIndented(...)\
    11 printf("\n%*s", indent * 2, ""); printf(__VA_ARGS__)
    12
    13class Serializer {
    14public:
    15 template <typename T>
    16 static void serialize(flecs::world& ecs, const T& value) {
    17 serialize(ecs, ecs.component<T>(), &value);
    18 }
    19
    20 static void serialize(
    21 flecs::world& ecs, flecs::entity type, const void *ptr)
    22 {
    23 // The TypeSerializer component contains a vector of instructions that
    24 // tells us how to serialize the type.
    25 const flecs::TypeSerializer& ts = type.get<flecs::TypeSerializer>();
    26
    27 Serializer{ecs}.serializeOps(
    28 ecs_vec_first_t(&ts.ops, flecs::meta::op_t),
    29 ecs_vec_count(&ts.ops), ptr);
    30 }
    31
    32private:
    33 Serializer(flecs::world& w) : ecs(w) { }
    34
    35 // Serialize contents of struct or collection scope
    36 void serializeScope(flecs::meta::op_t *ops, const void *ptr) {
    37 // A scope starts with a Push and ends with a Pop, so trim the first and
    38 // last instruction before forwarding.
    39 serializeOps(ops + 1, ops->op_count - 2, ptr);
    40 }
    41
    42 // Serialize a struct scope
    43 void serializeStruct(flecs::meta::op_t *ops,
    44 const void *ptr)
    45 {
    46 printf("{");
    47 indent ++;
    48
    49 serializeScope(ops, ptr);
    50
    51 indent --;
    52 printIndented("}");
    53 }
    54
    55 // Serialize an array scope
    56 void serializeArray(flecs::meta::op_t *ops,
    57 int32_t elem_count, const void *ptr)
    58 {
    59 printf("[");
    60
    61 // Iterate elements of the array. Skip the first and last instruction
    62 // since they are PushStruct and Pop.
    63 for (int i = 0; i < elem_count; i ++) {
    64 if (i) {
    65 printf(", ");
    66 }
    67
    68 serializeScope(ops, ptr);
    69
    70 ptr = ECS_OFFSET(ptr, ops->elem_size);
    71 }
    72
    73 printf("]");
    74 }
    75
    76 // Serialize a vector scope
    77 void serializeVector(flecs::meta::op_t *ops,
    78 const void *ptr)
    79 {
    80 auto vec = static_cast<const ecs_vec_t*>(ptr);
    81 serializeArray(ops, vec->count, vec->array);
    82 }
    83
    84 // Serialize enum
    85 void serializeEnum(flecs::meta::op_t *op, const void *ptr)
    86 {
    88 ecs_map_key_t value;
    89
    90 if (kind == EcsOpU8 || kind == EcsOpI8) {
    91 value = *static_cast<const uint8_t*>(ptr);
    92 } else if (kind == EcsOpU16 || kind == EcsOpI16) {
    93 value = *static_cast<const uint16_t*>(ptr);
    94 } else if (kind == EcsOpU32 || kind == EcsOpI32) {
    95 value = *static_cast<const uint32_t*>(ptr);
    96 } else if (kind == EcsOpUPtr || kind == EcsOpIPtr) {
    97 value = *static_cast<const uintptr_t*>(ptr);
    98 } else if (kind == EcsOpU64 || kind == EcsOpI64) {
    99 value = *static_cast<const uint64_t*>(ptr);
    100 } else {
    101 printf("<<invalid underlying enum type>>");
    102 return;
    103 }
    104
    105 ecs_enum_constant_t *c = ecs_map_get_deref(op->is.constants,
    106 ecs_enum_constant_t, value);
    107 printf("%s", c->name);
    108 }
    109
    110 // Iterate over instruction array
    111 void serializeOps(flecs::meta::op_t *ops, int32_t op_count,
    112 const void *base)
    113 {
    114 for (int i = 0; i < op_count; i ++) {
    115 flecs::meta::op_t *op = &ops[i];
    116
    117 // Member name
    118 if (op->name) {
    119 if (i) {
    120 printf(",");
    121 }
    122
    123 printIndented("%s: ", op->name);
    124 }
    125
    126 // Get pointer for current field
    127 void *ptr = ECS_OFFSET(base, op->offset);
    128
    129 switch(op->kind) {
    130 // Instructions that forward to a type scope, like a (nested) struct
    131 // or collection
    132 case EcsOpPushStruct:
    133 serializeStruct(op, ptr);
    134 break;
    135 case EcsOpPushArray:
    136 serializeArray(op, ecs_meta_op_get_elem_count(ops, ptr), ptr);
    137 break;
    138 case EcsOpPushVector:
    139 serializeVector(op, ptr);
    140 break;
    141
    142 // Opaque types have in-memory representations that are opaque to
    143 // the reflection framework and cannot be serialized by just taking
    144 // a pointer + an offset. See src/addons/script/serialize.c for an
    145 // example of how to handle opaque types.
    146 case EcsOpPushMap:
    147 case EcsOpPushValue:
    149 case EcsOpOpaqueArray:
    151 case EcsOpOpaqueValue:
    152 break;
    153
    154 // Forward to type. Used for members of array/vector types.
    155 case EcsOpForward:
    156 serialize(ecs, flecs::entity(ecs, op->type), ptr);
    157 break;
    158
    159 // Serialize single values
    160 case EcsOpEnum:
    161 serializeEnum(op, ptr);
    162 break;
    163 case EcsOpBitmask:
    164 // Bitmask serialization requires iterating all the bits in a
    165 // value and looking up the corresponding constant. For
    166 // an example, see src/addons/script/serialize.c.
    167 break;
    168 case EcsOpBool:
    169 printf("%s",
    170 (*static_cast<const bool*>(ptr)) ? "true" : "false");
    171 break;
    172 case EcsOpChar:
    173 printf("'%c'", *static_cast<const char*>(ptr));
    174 break;
    175 case EcsOpByte:
    176 case EcsOpU8:
    177 printf("%" PRIu8, *static_cast<const uint8_t*>(ptr));
    178 break;
    179 case EcsOpU16:
    180 printf("%" PRIu16, *static_cast<const uint16_t*>(ptr));
    181 break;
    182 case EcsOpU32:
    183 printf("%" PRIu32, *static_cast<const uint32_t*>(ptr));
    184 break;
    185 case EcsOpU64:
    186 printf("%" PRIu64, *static_cast<const uint64_t*>(ptr));
    187 break;
    188 case EcsOpI8:
    189 printf("%" PRIi8, *static_cast<const int8_t*>(ptr));
    190 break;
    191 case EcsOpI16:
    192 printf("%" PRIi16, *static_cast<const int16_t*>(ptr));
    193 break;
    194 case EcsOpI32:
    195 printf("%" PRIi32, *static_cast<const int32_t*>(ptr));
    196 break;
    197 case EcsOpI64:
    198 printf("%" PRIi64, *static_cast<const int64_t*>(ptr));
    199 break;
    200 case EcsOpF32:
    201 printf("%.2f",
    202 static_cast<double>(*static_cast<const float*>(ptr)));
    203 break;
    204 case EcsOpF64:
    205 printf("%.2f", *static_cast<const double*>(ptr));
    206 break;
    207 case EcsOpUPtr:
    208 printf("%" PRIuPTR, *static_cast<const uintptr_t*>(ptr));
    209 break;
    210 case EcsOpIPtr:
    211 printf("%" PRIiPTR, *static_cast<const intptr_t*>(ptr));
    212 break;
    213 case EcsOpString:
    214 printf("\"%s\"", *static_cast<const char**>(ptr));
    215 break;
    216 case EcsOpEntity: {
    217 flecs::entity e(ecs, *static_cast<flecs::entity_t*>(ptr));
    218 printf("%s\n", e.path().c_str());
    219 break;
    220 }
    221 case EcsOpId: {
    222 flecs::id component(ecs, *static_cast<flecs::id_t*>(ptr));
    223 printf("%s\n", component.str().c_str());
    224 break;
    225 }
    226 case EcsOpPop:
    227 case EcsOpScope:
    228 case EcsOpPrimitive:
    229 // Not serializable
    230 break;
    231 }
    232
    233 i += op->op_count - 1; // Skip over already processed instructions
    234 }
    235 }
    236
    237 flecs::world& ecs;
    238};
    239
    240// Some types to test the serializer with
    241
    242typedef struct {
    243 uint8_t red;
    244 uint8_t green;
    245 uint8_t blue;
    246} Rgb;
    247
    248typedef enum {
    249 Solid, Dashed
    250} StrokeKind;
    251
    252typedef struct {
    253 float x, y;
    254} Point;
    255
    256typedef struct {
    257 Rgb color;
    258 Rgb stroke_color;
    259 StrokeKind stroke_kind;
    260 ecs_vec_t points;
    261} Polygon;
    262
    263int main(int, char *[]) {
    264 flecs::world ecs;
    265
    266 // We need to register reflection data for our types before we can use them
    267 // with the serializer code.
    268
    269 ecs.component<Rgb>()
    270 .member(&Rgb::red, "red")
    271 .member(&Rgb::green, "green")
    272 .member(&Rgb::blue, "blue");
    273
    274 ecs.component<StrokeKind>();
    275
    276 ecs.component<Point>()
    277 .member(&Point::x, "x")
    278 .member(&Point::y, "y");
    279
    280 ecs.component<Polygon>()
    281 .member(&Polygon::color, "color")
    282 .member(&Polygon::stroke_color, "stroke_color")
    283 .member(&Polygon::stroke_kind, "stroke_kind")
    284 .member(ecs.vector<Point>(), "points");
    285
    286 // Create the value
    287 Polygon p = {};
    288 p.color = {0, 0, 255};
    289 p.stroke_color = {255, 0, 0};
    290 p.stroke_kind = Dashed;
    291 ecs_vec_init_t(NULL, &p.points, Point, 0);
    292 *ecs_vec_append_t(NULL, &p.points, Point) = {0, 0};
    293 *ecs_vec_append_t(NULL, &p.points, Point) = {1, 1};
    294 *ecs_vec_append_t(NULL, &p.points, Point) = {-1, 1};
    295
    296
    297 // Serialize value
    298 Serializer::serialize(ecs, p);
    299
    300 printf("\n");
    301
    302 // Output:
    303 // {
    304 // color: {
    305 // r: 0,
    306 // g: 0,
    307 // b: 255
    308 // },
    309 // stroke_color: {
    310 // r: 255,
    311 // g: 0,
    312 // b: 0
    313 // },
    314 // stroke_kind: Dashed,
    315 // points: [{
    316 // x: 0.00,
    317 // y: 0.00
    318 // }, {
    319 // x: 1.00,
    320 // y: 1.00
    321 // }, {
    322 // x: -1.00,
    323 // y: 1.00
    324 // }]
    325 // }
    326}
    struct ecs_enum_constant_t ecs_enum_constant_t
    Type that describes an enum constant.
    flecs::entity vector(flecs::entity_t elem_id)
    Create a vector type.
    Definition impl.hpp:132
    flecs::component< T > component(Args &&... args) const
    Find or register a component.
    Definition impl.hpp:11
    ecs_id_t id_t
    ID type.
    Definition c_types.hpp:20
    ecs_entity_t entity_t
    Entity type.
    Definition c_types.hpp:21
    Entity.
    Definition entity.hpp:30
    The world.
    Definition world.hpp:129
    flecs::entity entity(Args &&... args) const
    Create an entity.
    flecs::id id(E value) const
    Convert an enum constant to an entity.
    flecs::component< T > component(Args &&... args) const
    Find or register a component.