give the message serializer its own repo
This commit is contained in:
19
src/CMakeLists.txt
Normal file
19
src/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
cmake_minimum_required(VERSION 3.9...3.24 FATAL_ERROR)
|
||||
|
||||
project(solanaceae)
|
||||
|
||||
add_library(solanaceae_message_serializer
|
||||
./solanaceae/message3/message_serializer.hpp
|
||||
./solanaceae/message3/message_serializer.cpp
|
||||
)
|
||||
|
||||
target_include_directories(solanaceae_message_serializer PUBLIC .)
|
||||
target_compile_features(solanaceae_message_serializer PUBLIC cxx_std_17)
|
||||
target_link_libraries(solanaceae_message_serializer PUBLIC
|
||||
solanaceae_util
|
||||
solanaceae_message3
|
||||
nlohmann_json::nlohmann_json
|
||||
)
|
||||
|
||||
########################################
|
||||
|
120
src/solanaceae/message3/message_serializer.cpp
Normal file
120
src/solanaceae/message3/message_serializer.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include "./message_serializer.hpp"
|
||||
|
||||
#include <solanaceae/message3/components.hpp>
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static Contact3 findContactByID(Contact3Registry& cr, const std::vector<uint8_t>& id) {
|
||||
// TODO: id lookup table, this is very inefficent
|
||||
for (const auto& [c_it, id_it] : cr.view<Contact::Components::ID>().each()) {
|
||||
if (id == id_it.data) {
|
||||
return c_it;
|
||||
}
|
||||
}
|
||||
|
||||
return entt::null;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_get_json<Message::Components::ContactFrom>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) {
|
||||
const Contact3 c = h.get<Message::Components::ContactFrom>().c;
|
||||
if (!msc.cr.valid(c)) {
|
||||
// while this is invalid registry state, it is valid serialization
|
||||
j = nullptr;
|
||||
std::cerr << "MSC warning: encountered invalid contact\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!msc.cr.all_of<Contact::Components::ID>(c)) {
|
||||
// unlucky, this contact is purely ephemeral
|
||||
j = nullptr;
|
||||
std::cerr << "MSC warning: encountered contact without ID\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
j = nlohmann::json::binary(msc.cr.get<Contact::Components::ID>(c).data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components::ContactFrom>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j) {
|
||||
if (j.is_null()) {
|
||||
std::cerr << "MSC warning: encountered null contact\n";
|
||||
h.emplace_or_replace<Message::Components::ContactFrom>();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> id;
|
||||
if (j.is_binary()) {
|
||||
id = j.get_binary();
|
||||
} else {
|
||||
j["bytes"].get_to(id);
|
||||
}
|
||||
|
||||
Contact3 other_c = findContactByID(msc.cr, id);
|
||||
if (!msc.cr.valid(other_c)) {
|
||||
// create sparse contact with id only
|
||||
other_c = msc.cr.create();
|
||||
msc.cr.emplace_or_replace<Contact::Components::ID>(other_c, id);
|
||||
}
|
||||
|
||||
h.emplace_or_replace<Message::Components::ContactFrom>(other_c);
|
||||
|
||||
// TODO: should we return false if the contact is unknown??
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_get_json<Message::Components::ContactTo>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j) {
|
||||
const Contact3 c = h.get<Message::Components::ContactTo>().c;
|
||||
if (!msc.cr.valid(c)) {
|
||||
// while this is invalid registry state, it is valid serialization
|
||||
j = nullptr;
|
||||
std::cerr << "MSC warning: encountered invalid contact\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!msc.cr.all_of<Contact::Components::ID>(c)) {
|
||||
// unlucky, this contact is purely ephemeral
|
||||
j = nullptr;
|
||||
std::cerr << "MSC warning: encountered contact without ID\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
j = nlohmann::json::binary(msc.cr.get<Contact::Components::ID>(c).data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components::ContactTo>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j) {
|
||||
if (j.is_null()) {
|
||||
std::cerr << "MSC warning: encountered null contact\n";
|
||||
h.emplace_or_replace<Message::Components::ContactTo>();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> id;
|
||||
if (j.is_binary()) {
|
||||
id = j.get_binary();
|
||||
} else {
|
||||
j["bytes"].get_to(id);
|
||||
}
|
||||
|
||||
Contact3 other_c = findContactByID(msc.cr, id);
|
||||
if (!msc.cr.valid(other_c)) {
|
||||
// create sparse contact with id only
|
||||
other_c = msc.cr.create();
|
||||
msc.cr.emplace_or_replace<Contact::Components::ID>(other_c, id);
|
||||
}
|
||||
|
||||
h.emplace_or_replace<Message::Components::ContactTo>(other_c);
|
||||
|
||||
// TODO: should we return false if the contact is unknown??
|
||||
return true;
|
||||
}
|
||||
|
87
src/solanaceae/message3/message_serializer.hpp
Normal file
87
src/solanaceae/message3/message_serializer.hpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <entt/core/type_info.hpp>
|
||||
#include <entt/container/dense_map.hpp>
|
||||
|
||||
#include <solanaceae/message3/registry_message_model.hpp>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
struct MessageSerializerNJ {
|
||||
using Registry = Message3Registry;
|
||||
using Handle = Message3Handle;
|
||||
|
||||
Contact3Registry& cr;
|
||||
|
||||
// nlohmann
|
||||
// json/msgpack
|
||||
using serialize_fn = bool(*)(MessageSerializerNJ& msc, const Handle h, nlohmann::json& out);
|
||||
entt::dense_map<entt::id_type, serialize_fn> _serl_json;
|
||||
|
||||
using deserialize_fn = bool(*)(MessageSerializerNJ& msc, Handle h, const nlohmann::json& in);
|
||||
entt::dense_map<entt::id_type, deserialize_fn> _deserl_json;
|
||||
|
||||
template<typename T>
|
||||
static bool component_get_json(MessageSerializerNJ&, const Handle h, nlohmann::json& j) {
|
||||
if (h.template all_of<T>()) {
|
||||
if constexpr (!std::is_empty_v<T>) {
|
||||
j = h.template get<T>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool component_emplace_or_replace_json(MessageSerializerNJ&, Handle h, const nlohmann::json& j) {
|
||||
if constexpr (std::is_empty_v<T>) {
|
||||
h.template emplace_or_replace<T>(); // assert empty json?
|
||||
} else {
|
||||
h.template emplace_or_replace<T>(static_cast<T>(j));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void registerSerializer(serialize_fn fn, const entt::type_info& type_info) {
|
||||
_serl_json[type_info.hash()] = fn;
|
||||
}
|
||||
|
||||
template<typename CompType>
|
||||
void registerSerializer(
|
||||
serialize_fn fn = component_get_json<CompType>,
|
||||
const entt::type_info& type_info = entt::type_id<CompType>()
|
||||
) {
|
||||
registerSerializer(fn, type_info);
|
||||
}
|
||||
|
||||
void registerDeserializer(deserialize_fn fn, const entt::type_info& type_info) {
|
||||
_deserl_json[type_info.hash()] = fn;
|
||||
}
|
||||
|
||||
template<typename CompType>
|
||||
void registerDeserializer(
|
||||
deserialize_fn fn = component_emplace_or_replace_json<CompType>,
|
||||
const entt::type_info& type_info = entt::type_id<CompType>()
|
||||
) {
|
||||
registerDeserializer(fn, type_info);
|
||||
}
|
||||
|
||||
// TODO: deregister
|
||||
};
|
||||
|
||||
// fwd
|
||||
namespace Message::Components {
|
||||
struct ContactFrom;
|
||||
struct ContactTo;
|
||||
}
|
||||
|
||||
// make specializations known
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_get_json<Message::Components::ContactFrom>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j);
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components::ContactFrom>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j);
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_get_json<Message::Components::ContactTo>(MessageSerializerNJ& msc, const Handle h, nlohmann::json& j);
|
||||
template<>
|
||||
bool MessageSerializerNJ::component_emplace_or_replace_json<Message::Components::ContactTo>(MessageSerializerNJ& msc, Handle h, const nlohmann::json& j);
|
Reference in New Issue
Block a user