response serialisation/deserialisation

This commit is contained in:
snit 2024-10-22 20:25:27 -05:00
parent 3470d4bebc
commit c32af03d20
5 changed files with 261 additions and 22 deletions

View File

@ -40,6 +40,7 @@ struct response_body_get_world_data_t {
struct response_t { struct response_t {
enum request_type_t type;
bool success; bool success;
void *body; void *body;
// The body's type depends on the request's type // The body's type depends on the request's type

View File

@ -22,11 +22,14 @@ struct world_t {
enum error_t world_init(struct world_t *, size_t, size_t); enum error_t world_init(struct world_t *, size_t, size_t);
void world_free(struct world_t *); void world_free(struct world_t *);
enum error_t world_serialise_str(struct world_t *, char const **); enum error_t world_serialise(struct world_t const *, struct json_t **);
enum error_t world_deserialise(struct world_t *, struct json_t *);
enum error_t world_serialise_str(struct world_t const *, char const **);
enum error_t world_deserialise_str(struct world_t *, char const *); enum error_t world_deserialise_str(struct world_t *, char const *);
// Operates on strings; serialise allocates so make sure to free // Operates on strings; serialise allocates so make sure to free
enum error_t world_serialise_buf(struct world_t *, char *, size_t); enum error_t world_serialise_buf(struct world_t const *, char *, size_t);
// Operates on buffers; need not be zero-terminated // Operates on buffers; need not be zero-terminated
enum error_t world_register_entity(struct world_t *, char const *, char); enum error_t world_register_entity(struct world_t *, char const *, char);

View File

@ -11,6 +11,9 @@ static char const *REQUEST_JSON_FMT = "{si, so}";
static char const *REQUEST_BODY_GET_WORLD_DATA_JSON_FMT = "{sI}"; static char const *REQUEST_BODY_GET_WORLD_DATA_JSON_FMT = "{sI}";
// Response Format Strings // Response Format Strings
static char const *RESPONSE_JSON_FMT = "{sb, si, so}";
static char const *RESPONSE_BODY_GET_WORLD_DATA_JSON_FMT = "{so}";
static enum error_t request_serialise_body_get_world_data( static enum error_t request_serialise_body_get_world_data(
@ -44,6 +47,7 @@ static enum error_t request_serialise_body(
default: return ERR_JSON_SERIALISE; default: return ERR_JSON_SERIALISE;
} }
return ERR_OK; return ERR_OK;
} }
@ -237,16 +241,233 @@ enum error_t request_deserialise_str(struct request_t *self, char const *str) {
} }
static enum error_t response_serialise_body_get_world_data(
struct response_body_get_world_data_t const *self,
struct json_t **jsonptr
) {
assert(self != NULL);
assert(jsonptr != NULL);
struct json_t *json = NULL;
enum error_t err = world_serialise(&self->world, &json);
if (err != ERR_OK) return err;
*jsonptr = json;
return ERR_OK;
}
static enum error_t response_serialise_body(
struct response_t const *self,
struct json_t **jsonptr
) {
assert(self != NULL);
assert(jsonptr != NULL);
switch (self->type) {
case REQUEST_GET_WORLD_DATA:
return response_serialise_body_get_world_data(self->body, jsonptr);
default: return ERR_JSON_SERIALISE;
}
return ERR_OK;
}
static enum error_t response_serialise_parts(
struct json_t *body_json, enum request_type_t request_type, bool success,
struct json_t **jsonptr
) {
assert(body_json != NULL);
assert(jsonptr != NULL);
struct json_t *json = json_pack(RESPONSE_JSON_FMT,
"success", success,
"request-code", request_type,
"response", body_json
);
if (json == NULL) return ERR_JSON_SERIALISE;
*jsonptr = json;
return ERR_OK;
}
static enum error_t response_serialise(
struct response_t const *self,
struct json_t **jsonptr
) {
assert(self != NULL);
assert(jsonptr != NULL);
// Serialise response body
struct json_t *body_json = NULL;
enum error_t err = response_serialise_body(self, &body_json);
if (err != ERR_OK) return err;
// Serialise full structure
struct json_t *response_json = NULL;
err = response_serialise_parts(
body_json, self->success, self->type,
&response_json
);
if (err != ERR_OK) {
json_decref(body_json);
return err;
}
*jsonptr = response_json;
return ERR_OK;
}
enum error_t response_serialise_str( enum error_t response_serialise_str(
struct response_t const *self, struct response_t const *self,
char const **strptr char const **strptr
); ) {
assert(self != NULL);
assert(strptr != NULL);
struct json_t *json = NULL;
enum error_t err = response_serialise(self, &json);
if (err != ERR_OK) return err;
const char *str = json_dumps(json, 0);
if (str == NULL) {
json_decref(json);
return ERR_JSON_SERIALISE;
}
json_decref(json);
*strptr = str;
return ERR_OK;
}
enum error_t response_serialise_buf( enum error_t response_serialise_buf(
struct response_t const *self, struct response_t const *self,
char *buf, size_t len char *buf, size_t len
) {
assert(self != NULL);
assert(buf != NULL);
assert(len > 0);
struct json_t *json = NULL;
enum error_t err = response_serialise(self, &json);
if (err != ERR_OK) return err;
size_t bytes_written = json_dumpb(json, buf, len, 0);
if (bytes_written == 0) {
json_decref(json);
return ERR_JSON_SERIALISE;
}
json_decref(json);
return ERR_OK;
}
static enum error_t response_deserialise_parts(
struct json_t **body_json,
enum request_type_t *type,
bool *success,
struct json_t *json
) {
assert(body_json != NULL);
assert(type != NULL);
assert(success != NULL);
assert(json != NULL);
int err = json_unpack(json, RESPONSE_JSON_FMT,
"success", success,
"request-code", type,
"response", body_json
); );
if (err < 0) return ERR_JSON_DESERIALISE;
return ERR_OK;
}
enum error_t response_deserialise_str(struct response_t *self, char const *str);
static enum error_t response_deserialise_body_get_world_data(
struct response_body_get_world_data_t *self,
struct json_t *json
) {
assert(self != NULL);
assert(json != NULL);
enum error_t err = world_deserialise(&self->world, json);
if (err != ERR_OK) return err;
return ERR_OK;
}
static enum error_t response_deserialise_body(
struct response_t *self,
struct json_t *json
) {
assert(self != NULL);
assert(json != NULL);
switch (self->type) {
case REQUEST_GET_WORLD_DATA:
self->body = malloc(sizeof(struct response_body_get_world_data_t));
if (self->body == NULL) return ERR_ALLOC;
return response_deserialise_body_get_world_data(self->body, json);
default: return ERR_JSON_SERIALISE;
}
}
static enum error_t response_deserialise(
struct response_t *self,
struct json_t *json
) {
assert(self != NULL);
assert(json != NULL);
struct response_t temp_response = { 0 };
struct json_t *body_json = NULL;
enum error_t err = response_deserialise_parts(
&body_json, &temp_response.type, &temp_response.success, json
);
if (err != ERR_OK) return err;
err = response_deserialise_body(&temp_response, body_json);
if (err != ERR_OK) {
json_decref(body_json);
return err;
}
*self = temp_response;
return ERR_OK;
}
enum error_t response_deserialise_str(
struct response_t *self,
char const *str
) {
assert(self != NULL);
assert(str != NULL);
struct json_t *json = json_loads(str, 0, NULL);
if (json == NULL) return ERR_JSON_DESERIALISE;
enum error_t err = response_deserialise(self, json);
if (err != ERR_OK) {
json_decref(json);
return err;
}
json_decref(json);
return ERR_OK;
}

View File

@ -104,7 +104,10 @@ static enum error_t world_serialise_parts(
} }
static enum error_t world_serialise(struct world_t *self, struct json_t **json) { enum error_t world_serialise(
struct world_t const *self,
struct json_t **json
) {
assert(self != NULL); assert(self != NULL);
assert(json != NULL); assert(json != NULL);
@ -212,7 +215,7 @@ static enum error_t world_deserialise_entities(
} }
static enum error_t world_deserialise(struct world_t *self, struct json_t *json) { enum error_t world_deserialise(struct world_t *self, struct json_t *json) {
assert(self != NULL); assert(self != NULL);
assert(json != NULL); assert(json != NULL);
@ -256,7 +259,10 @@ error:
} }
enum error_t world_serialise_str(struct world_t *self, char const **strptr) { enum error_t world_serialise_str(
struct world_t const *self,
char const **strptr
) {
assert(self != NULL); assert(self != NULL);
assert(strptr != NULL); assert(strptr != NULL);
@ -277,7 +283,10 @@ enum error_t world_serialise_str(struct world_t *self, char const **strptr) {
} }
enum error_t world_serialise_buf(struct world_t *self, char *buf, size_t len) { enum error_t world_serialise_buf(
struct world_t const *self,
char *buf, size_t len
) {
assert(self != NULL); assert(self != NULL);
assert(buf != NULL); assert(buf != NULL);
assert(len > 0); assert(len > 0);

View File

@ -27,25 +27,30 @@ enum error_t game_loop(struct data_t *data) {
enum error_t err = ERR_OK; enum error_t err = ERR_OK;
// TEMP // TEMP
struct request_body_get_world_data_t request_body = { 69 }; struct response_body_get_world_data_t response_body = { data->world };
struct request_t request = { REQUEST_GET_WORLD_DATA, &request_body }; struct response_t response = { true, REQUEST_GET_WORLD_DATA, &response_body };
char const *request_json_str = NULL; char const *response_json_str = NULL;
err = request_serialise_str(&request, &request_json_str); err = response_serialise_str(&response, &response_json_str);
if (err) return err; if (err) return err;
printf("serialised request: %s\n", request_json_str); printf("serialised response: %s\n", response_json_str);
struct request_t request2 = { 0 }; struct response_t response2 = { 0 };
err = request_deserialise_str(&request2, request_json_str); err = response_deserialise_str(&response2, response_json_str);
if (err) return err; if (err) return err;
struct request_body_get_world_data_t *request2_body = request2.body; struct response_body_get_world_data_t *response2_body = response2.body;
printf("deserialised request: (%d, %zu)\n",
request2.type, char const *world_json_str = NULL;
request2_body->world_id err = world_serialise_str(&response2_body->world, &world_json_str);
if (err) return err;
printf("deserialised response: (%d, %d, %s\n",
response2.success,
response2.type,
world_json_str
); );
free((void *)request_json_str); free((void *)response_json_str);
// TEMP // TEMP