Skip to content

Commit

Permalink
Cleanup & fix inconsistencies in REST API
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Jun 21, 2024
1 parent c28916b commit 8af0f65
Show file tree
Hide file tree
Showing 15 changed files with 1,124 additions and 546 deletions.
362 changes: 278 additions & 84 deletions docs/FlecsRemoteApi.md

Large diffs are not rendered by default.

395 changes: 273 additions & 122 deletions flecs.c

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -13248,6 +13248,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_doc; /**< Serialize doc attributes */
bool serialize_var_labels; /**< Serialize doc names of matched variables */
bool serialize_full_paths; /**< Serialize full paths for tags, components and pairs */
bool serialize_fields; /**< Serialize field data */
bool serialize_inherited; /**< Serialize inherited components */
bool serialize_table; /**< Serialize entire table vs. matched components */
bool serialize_type_info; /**< Serialize type information */
Expand All @@ -13268,6 +13269,7 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_values = true, \
.serialize_doc = false, \
.serialize_full_paths = false, \
.serialize_fields = true, \
.serialize_inherited = false, \
.serialize_table = false, \
.serialize_type_info = false, \
Expand Down
2 changes: 2 additions & 0 deletions include/flecs/addons/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ typedef struct ecs_iter_to_json_desc_t {
bool serialize_doc; /**< Serialize doc attributes */
bool serialize_var_labels; /**< Serialize doc names of matched variables */
bool serialize_full_paths; /**< Serialize full paths for tags, components and pairs */
bool serialize_fields; /**< Serialize field data */
bool serialize_inherited; /**< Serialize inherited components */
bool serialize_table; /**< Serialize entire table vs. matched components */
bool serialize_type_info; /**< Serialize type information */
Expand All @@ -295,6 +296,7 @@ typedef struct ecs_iter_to_json_desc_t {
.serialize_values = true, \
.serialize_doc = false, \
.serialize_full_paths = false, \
.serialize_fields = true, \
.serialize_inherited = false, \
.serialize_table = false, \
.serialize_type_info = false, \
Expand Down
2 changes: 1 addition & 1 deletion src/addons/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ void http_append_send_headers(
ecs_strbuf_appendlit(hdrs, "Access-Control-Allow-Origin: *\r\n");
if (preflight) {
ecs_strbuf_appendlit(hdrs, "Access-Control-Allow-Private-Network: true\r\n");
ecs_strbuf_appendlit(hdrs, "Access-Control-Allow-Methods: GET, PUT, OPTIONS\r\n");
ecs_strbuf_appendlit(hdrs, "Access-Control-Allow-Methods: GET, PUT, DELETE, OPTIONS\r\n");
ecs_strbuf_appendlit(hdrs, "Access-Control-Max-Age: 600\r\n");
}

Expand Down
204 changes: 155 additions & 49 deletions src/addons/json/serialize_iter_result_query.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ bool flecs_json_serialize_iter_result_is_set(
flecs_json_memberl(buf, "is_set");
flecs_json_array_push(buf);

for (int i = 0; i < it->field_count; i ++) {
int32_t i, count = it->field_count;
for (i = 0; i < count; i ++) {
ecs_strbuf_list_next(buf);
if (ecs_field_is_set(it, i)) {
flecs_json_true(buf);
Expand All @@ -33,25 +34,126 @@ bool flecs_json_serialize_iter_result_is_set(
return true;
}

static
bool flecs_json_serialize_iter_result_ids(
const ecs_iter_t *it,
ecs_strbuf_t *buf)
{
const ecs_query_t *q = it->query;
if (!q) {
return false;
}

ecs_world_t *world = it->world;
int16_t f, field_count = flecs_ito(int16_t, it->field_count);
int16_t field_mask = flecs_ito(int16_t, (1u << field_count) - 1);
if (q->static_id_fields == field_mask) {
/* All matched ids are static, nothing to serialize */
return false;
}

flecs_json_memberl(buf, "ids");
flecs_json_array_push(buf);

for (f = 0; f < field_count; f ++) {
ecs_flags16_t field_bit = flecs_ito(uint16_t, 1 << f);;

if (!(it->set_fields & field_bit)) {
/* Don't serialize ids for fields that aren't set */
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

if (q->static_id_fields & field_bit) {
/* Only add non-static ids to save bandwidth/performance */
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

flecs_json_next(buf);
flecs_json_id(buf, world, it->ids[f]);
}

flecs_json_array_pop(buf);

return true;
}

static
bool flecs_json_serialize_iter_result_sources(
const ecs_iter_t *it,
ecs_strbuf_t *buf)
{
const ecs_query_t *q = it->query;
if (!q) {
return false;
}

ecs_world_t *world = it->world;
int32_t f, field_count = it->field_count;

for (f = 0; f < field_count; f ++) {
if (it->sources[f]) {
break;
}
}

if (f == field_count) {
/* All fields are mathced on $this */
return false;
}

flecs_json_memberl(buf, "sources");
flecs_json_array_push(buf);

for (f = 0; f < field_count; f ++) {
ecs_flags16_t field_bit = flecs_ito(uint16_t, 1 << f);;

if (!(it->set_fields & field_bit)) {
/* Don't serialize source for fields that aren't set */
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

if (!it->sources[f]) {
/* Don't serialize source for fields that have $this source */
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

flecs_json_next(buf);
flecs_json_path(buf, world, it->sources[f]);
}

flecs_json_array_pop(buf);

return true;
}

static
bool flecs_json_serialize_common_for_table(
const ecs_world_t *world,
const ecs_iter_t *it,
ecs_strbuf_t *buf,
const ecs_iter_to_json_desc_t *desc)
{
bool result = false;
ecs_strbuf_list_push(buf, "", ",");
result |= flecs_json_serialize_vars(world, it, buf, desc);
result |= flecs_json_serialize_iter_result_is_set(it, buf);
ecs_strbuf_list_pop(buf, "");
if (!result) {
ecs_strbuf_reset(buf);
flecs_json_serialize_vars(world, it, buf, desc);

bool result = false;
if (!desc || desc->serialize_fields) {
ecs_strbuf_list_appendlit(buf, "\"fields\":");
flecs_json_object_push(buf);
result |= flecs_json_serialize_iter_result_is_set(it, buf);
result |= flecs_json_serialize_iter_result_ids(it, buf);
result |= flecs_json_serialize_iter_result_sources(it, buf);
}

ecs_strbuf_list_pop(buf, "");
return result;
}

int flecs_json_serialize_iter_result_fields(
int flecs_json_serialize_iter_result_field_values(
const ecs_world_t *world,
const ecs_iter_t *it,
int32_t i,
Expand All @@ -64,55 +166,38 @@ int flecs_json_serialize_iter_result_fields(
return 0;
}

flecs_json_memberl(buf, "fields");
ecs_strbuf_appendlit(buf, "\"values\":");
flecs_json_array_push(buf);

for (f = 0; f < field_count; f ++) {
flecs_json_next(buf);

ecs_flags16_t field_bit = flecs_ito(uint16_t, 1 << f);;
flecs_json_object_push(buf);

if (!(it->set_fields & field_bit)) {
goto next;
}

if (it->query) {
if (!(it->query->static_id_fields & field_bit)) {
flecs_json_memberl(buf, "id");
flecs_json_id(buf, world, it->ids[f]);
}
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

if (it->sources[f]) {
flecs_json_memberl(buf, "source");
flecs_json_path(buf, world, it->sources[f]);
}


ecs_json_value_ser_ctx_t *value_ctx = &ser_ctx->value_ctx[f];
if (!flecs_json_serialize_get_value_ctx(
world, it->ids[f], value_ctx, desc))
{
goto next;
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

if (!it->ptrs[f]) {
goto next; /* Should not happen, but don't panic on it */
ecs_strbuf_list_appendlit(buf, "0");
continue;
}

flecs_json_memberl(buf, "data");

void *ptr = it->ptrs[f];
if (!it->sources[f]) {
ptr = ECS_ELEM(ptr, it->sizes[f], i);
}

flecs_json_next(buf);
if (flecs_json_ser_type(world, &value_ctx->ser->ops, ptr, buf) != 0) {
return -1;
}

next:
flecs_json_object_pop(buf);
}

flecs_json_array_pop(buf);
Expand All @@ -132,14 +217,15 @@ int flecs_json_serialize_iter_result_query(
const ecs_json_this_data_t *this_data)
{
/* Serialize tags, pairs, vars once, since they're the same for each row */
ecs_strbuf_t tags_pairs_vars_buf = ECS_STRBUF_INIT;
int32_t tags_pairs_vars_len = 0;
char *tags_pairs_vars = NULL;
if (flecs_json_serialize_common_for_table(
world, it, &tags_pairs_vars_buf, desc))
{
tags_pairs_vars_len = ecs_strbuf_written(&tags_pairs_vars_buf);
tags_pairs_vars = ecs_strbuf_get(&tags_pairs_vars_buf);
ecs_strbuf_t common_data_buf = ECS_STRBUF_INIT;
bool common_field_data = flecs_json_serialize_common_for_table(
world, it, &common_data_buf, desc);
int32_t common_data_len = ecs_strbuf_written(&common_data_buf);
char *common_data = NULL;
if (!common_data_len) {
ecs_strbuf_reset(&common_data_buf);
} else {
common_data = ecs_strbuf_get(&common_data_buf);
}

int32_t i;
Expand All @@ -152,21 +238,41 @@ int flecs_json_serialize_iter_result_query(
it, parent_path, this_data, i, buf, desc);
}

if (tags_pairs_vars) {
if (common_data) {
ecs_strbuf_list_appendstrn(buf,
tags_pairs_vars, tags_pairs_vars_len);
common_data, common_data_len);
}

if (flecs_json_serialize_iter_result_fields(
world, it, i, buf, desc, ser_ctx))
{
return -1;
if (!desc || desc->serialize_fields) {
bool has_values = !desc || desc->serialize_values;
if (it->flags & EcsIterNoData || !it->field_count) {
has_values = false;
}

const ecs_query_t *q = it->query;
if (q && !q->data_fields) {
has_values = false;
}

if (has_values) {
if (common_field_data) {
flecs_json_next(buf);
}

if (flecs_json_serialize_iter_result_field_values(
world, it, i, buf, desc, ser_ctx))
{
return -1;
}
}

ecs_strbuf_appendstr(buf, "}"); // "fields": {
}

flecs_json_object_pop(buf);
}

ecs_os_free(tags_pairs_vars);
ecs_os_free(common_data);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/addons/json/serialize_query_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void flecs_json_serialize_term(
flecs_json_memberl(buf, "inout");
flecs_json_string(buf, flecs_json_inout_str(term->inout));

flecs_json_memberl(buf, "has_data");
flecs_json_memberl(buf, "has_value");
flecs_json_bool(buf, 0 == (term->flags_ & EcsTermNoData));

ecs_entity_t first_id = ECS_TERM_REF_ID(&term->first);
Expand Down
Loading

0 comments on commit 8af0f65

Please sign in to comment.