#pragma once #include #include #include #include "network_byte_order.h" typedef uint8_t uint8; #define ARRAY_OF uint8 #include "array.h" typedef struct struct_descriptor_s struct_descriptor_t; typedef void (*serializer_function_t)(uint8_t *); typedef struct field_descriptor{ char const *name; ptrdiff_t offset; size_t size; serializer_function_t serializer; } field_descriptor_t; #define ARRAY_OF struct field_descriptor #include "array.h" typedef struct struct_descriptor_s{ char const *name; size_t size; field_descriptor_arr_t fields; } struct_descriptor_t; #include "narg.h" #include "for_each.h" #define default_serializer_function(s) __extension__({ \ (s == 64) ? serialize_64bits : ( \ (s == 32) ? serialize_32bits : ( \ (s == 16) ? serialize_16bits : \ serialize_generic ));\ }) #define sizeof_field(T, field) sizeof(((T *)NULL)->field) #define describe_field(T, field) ((field_descriptor_t) {.name = #field, .offset = offsetof(T, field), .size = sizeof_field(T, field), .serializer = default_serializer_function(sizeof_field(T, field))}) #define describe_fields(T, ...) for_each_pair(describe_field, T, __VA_ARGS__) #define describe_type(T, ...) struct_descriptor_init(#T, sizeof(T), NARG(__VA_ARGS__) __VA_OPT__(, describe_fields(T, __VA_ARGS__))) struct_descriptor_t *struct_descriptor_init(char const *name, size_t size, size_t count, ...); #define register_type(T, ...) struct_descriptor_register(#T, sizeof(T), NARG(__VA_ARGS__) __VA_OPT__(, describe_fields(T, __VA_ARGS__))) void struct_descriptor_register(char const *name, size_t size, size_t count, ...); #define serialize_type(T, data) struct_descriptor_serialize_data(#T, data) uint8_arr_t *struct_descriptor_serialize_data(char const *name, void *data); #define deserialize_data(T, data) (T *) struct_descriptor_deserialize_data(#T, data) void *struct_descriptor_deserialize_data(char const *name, uint8_arr_t *data); bool struct_descriptor_set_serializer(char const *name, char const *field, serializer_function_t serializer); void print_struct_descriptor(struct_descriptor_t *descriptor); void serialize_64bits(void *data); void serialize_32bits(void *data); void serialize_16bits(void *data); void serialize_generic(void *data);