Skip to content

Commit

Permalink
#924 Serialization support for opaque types
Browse files Browse the repository at this point in the history
* #712 Add serialization support for custom types

* Add C++ API for custom type reflection

* #712 Add C++ tests

* Decode URL strings in HTTP addon

* Add support for custom struct serialization, add tests

* Add more tests, improve naming, code cleanup

* Add examples, more API cleanup
  • Loading branch information
SanderMertens committed Feb 2, 2023
1 parent 86c7cce commit 31fa902
Show file tree
Hide file tree
Showing 39 changed files with 2,561 additions and 427 deletions.
16 changes: 16 additions & 0 deletions examples/cpp/reflection/ser_opaque_type/include/ser_opaque_type.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef SER_OPAQUE_TYPE_H
#define SER_OPAQUE_TYPE_H

/* This generated file contains includes for project dependencies */
#include "ser_opaque_type/bake_config.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
)
(.)
.|.
| |
_.--| |--._
.-'; ;`-'& ; `&.
\ & ; & &_/
|"""---...---"""|
\ | | | | | | | /
`---.|.|.|.---'
* This file is generated by bake.lang.c for your convenience. Headers of
* dependencies will automatically show up in this file. Include bake_config.h
* in your main project file. Do not edit! */

#ifndef SER_OPAQUE_TYPE_BAKE_CONFIG_H
#define SER_OPAQUE_TYPE_BAKE_CONFIG_H

/* Headers of public dependencies */
#include <flecs.h>

#endif

11 changes: 11 additions & 0 deletions examples/cpp/reflection/ser_opaque_type/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "ser_opaque_type",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}
49 changes: 49 additions & 0 deletions examples/cpp/reflection/ser_opaque_type/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <ser_opaque_type.h>
#include <iostream>
#include <string>

// This example shows how to serialize a type with private members and public
// getter methods.

struct OpaqueType {
OpaqueType(double x, double y) : x_(x), y_(y) { }

double x() const { return x_; }
double y() const { return y_; }

private:
double x_;
double y_;
};

// Serializer function for std::string
int opaque_ser(const flecs::serializer *s, const OpaqueType *data) {
s->member("x"); // Serializer-specific function to insert member
s->value(data->x()); // Serializer specific function to insert double value
s->member("y");
s->value(data->y());
return 0;
}

int main(int, char *[]) {
flecs::world ecs;

// Create struct type that represents the opaque type
flecs::entity as_struct = ecs.component()
.member<double>("x")
.member<double>("y");

// Register serialization support for std::string
ecs.component<OpaqueType>()
.serialize(
as_struct, // Describes what the serialized output looks like
opaque_ser); // Serializer function

// Create dummy value & serialize it
OpaqueType v = {10, 20};
auto json = ecs.to_json(&v);
std::cout << json << std::endl;

// Output:
// {"x":10, "y":20}
}
16 changes: 16 additions & 0 deletions examples/cpp/reflection/ser_std_string/include/ser_std_string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef SER_STD_STRING_H
#define SER_STD_STRING_H

/* This generated file contains includes for project dependencies */
#include "ser_std_string/bake_config.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
)
(.)
.|.
| |
_.--| |--._
.-'; ;`-'& ; `&.
\ & ; & &_/
|"""---...---"""|
\ | | | | | | | /
`---.|.|.|.---'
* This file is generated by bake.lang.c for your convenience. Headers of
* dependencies will automatically show up in this file. Include bake_config.h
* in your main project file. Do not edit! */

#ifndef SER_STD_STRING_BAKE_CONFIG_H
#define SER_STD_STRING_BAKE_CONFIG_H

/* Headers of public dependencies */
#include <flecs.h>

#endif

11 changes: 11 additions & 0 deletions examples/cpp/reflection/ser_std_string/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "ser_std_string",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}
40 changes: 40 additions & 0 deletions examples/cpp/reflection/ser_std_string/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <ser_std_string.h>
#include <iostream>
#include <string>

// This example shows how to serialize a component with an std::string

struct StringComponent {
std::string a;
std::string b;
};

// Serializer function for std::string
int std_string_ser(const flecs::serializer *s, const std::string *data) {
const char *str = data->c_str();
s->value(flecs::String, &str); // Serializer-specific string serialization
return 0;
}

int main(int, char *[]) {
flecs::world ecs;

// Register serialization support for std::string
ecs.component<std::string>()
.serialize(
flecs::String, // Describes what the serialized output looks like
std_string_ser); // Serializer function

// Register component with std::string members
ecs.component<StringComponent>()
.member<std::string>("a")
.member<std::string>("b");

// Create dummy value & serialize it
StringComponent v = {"foo", "bar"};
auto json = ecs.to_json(&v);
std::cout << json << std::endl;

// Output:
// {"a": "foo", "b": "bar"}
}
16 changes: 16 additions & 0 deletions examples/cpp/reflection/ser_std_vector/include/ser_std_vector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef SER_STD_VECTOR_H
#define SER_STD_VECTOR_H

/* This generated file contains includes for project dependencies */
#include "ser_std_vector/bake_config.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

#endif

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
)
(.)
.|.
| |
_.--| |--._
.-'; ;`-'& ; `&.
\ & ; & &_/
|"""---...---"""|
\ | | | | | | | /
`---.|.|.|.---'
* This file is generated by bake.lang.c for your convenience. Headers of
* dependencies will automatically show up in this file. Include bake_config.h
* in your main project file. Do not edit! */

#ifndef SER_STD_VECTOR_BAKE_CONFIG_H
#define SER_STD_VECTOR_BAKE_CONFIG_H

/* Headers of public dependencies */
#include <flecs.h>

#endif

11 changes: 11 additions & 0 deletions examples/cpp/reflection/ser_std_vector/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "ser_std_vector",
"type": "application",
"value": {
"use": [
"flecs"
],
"language": "c++",
"public": false
}
}
62 changes: 62 additions & 0 deletions examples/cpp/reflection/ser_std_vector/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <ser_std_vector.h>
#include <iostream>
#include <string>
#include <vector>

// This example shows how to serialize a component with std::vectors

struct VectorComponent {
std::vector<int32_t> ints;
std::vector<std::string> strings;
};

// Serializer function for std::string
int std_string_ser(const flecs::serializer *s, const std::string *data) {
const char *str = data->c_str();
s->value(flecs::String, &str); // Serializer-specific string serialization
return 0;
}

// Serializer function for std::vector
template <typename Elem>
int std_vector_ser(const flecs::serializer *s, const std::vector<Elem> *data) {
for (const auto& el : *data) {
s->value(el);
}
return 0;
}

int main(int, char *[]) {
flecs::world ecs;

// Register serialization support for std::string
ecs.component<std::string>()
.serialize(
flecs::String, // Describes what the serialized output looks like
std_string_ser); // Serializer function

// Register serialization support for std::vector<int>
ecs.component<std::vector<int>>()
.serialize(
ecs.vector<int32_t>(),
std_vector_ser<int32_t>);

// Register serialization support for std::vector<std::string>
ecs.component<std::vector<std::string>>()
.serialize(
ecs.vector<std::string>(),
std_vector_ser<std::string>);

// Register component with std::string members
ecs.component<VectorComponent>()
.member<std::vector<int>>("ints")
.member<std::vector<std::string>>("strings");

// Create dummy value & serialize it
VectorComponent v = {{1, 2, 3}, {"foo", "bar"}};
auto json = ecs.to_json(&v);
std::cout << json << std::endl;

// Output:
// {"ints":[1, 2, 3], "strings":["foo", "bar"]}
}
Loading

0 comments on commit 31fa902

Please sign in to comment.