refactor message serializer to allow access to eg contacts

This commit is contained in:
Green Sky 2024-02-16 16:29:37 +01:00
parent 73d1d65142
commit 1bfd04680e
No known key found for this signature in database
5 changed files with 185 additions and 6 deletions

View File

@ -19,6 +19,8 @@ target_link_libraries(fragment_store PUBLIC
########################################
add_library(message_fragment_store
./fragment_store/message_serializer.hpp
./fragment_store/message_serializer.cpp
./fragment_store/message_fragment_store.hpp
./fragment_store/message_fragment_store.cpp
)

View File

@ -209,7 +209,7 @@ MessageFragmentStore::MessageFragmentStore(
Contact3Registry& cr,
RegistryMessageModel& rmm,
FragmentStore& fs
) : _cr(cr), _rmm(rmm), _fs(fs) {
) : _cr(cr), _rmm(rmm), _fs(fs), _sc{_cr, {}, {}} {
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
_rmm.subscribe(this, RegistryMessageModel_Event::message_updated);
_rmm.subscribe(this, RegistryMessageModel_Event::message_destroy);
@ -292,7 +292,7 @@ float MessageFragmentStore::tick(float time_delta) {
continue;
}
s_cb_it->second({*reg, m}, j_entry[storage.type().name()]);
s_cb_it->second(_sc, {*reg, m}, j_entry[storage.type().name()]);
}
}

View File

@ -4,6 +4,8 @@
#include "./fragment_store_i.hpp"
#include "./fragment_store.hpp"
#include "./message_serializer.hpp"
#include <entt/entity/registry.hpp>
#include <entt/container/dense_map.hpp>
@ -36,10 +38,6 @@ namespace Fragment::Components {
};
} // Fragment::Components
struct MessageSerializerCallbacks : public SerializerCallbacks<Message3> {
// TODO: add contact and message reg, so entities can be looked up and be converted to fragment uids OR persistent ids
};
// handles fragments for messages
// on new message: assign fuid
// on new and update: mark as fragment dirty

View File

@ -0,0 +1,94 @@
#include "./message_serializer.hpp"
#include <solanaceae/message3/components.hpp>
#include <solanaceae/contact/components.hpp>
#include <nlohmann/json.hpp>
#include <iostream>
template<>
bool MessageSerializerCallbacks::component_get_json<Message::Components::ContactFrom>(MessageSerializerCallbacks& 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 MessageSerializerCallbacks::component_emplace_or_replace_json<Message::Components::ContactFrom>(MessageSerializerCallbacks& 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;
}
const auto id = static_cast<std::vector<uint8_t>>(j);
// TODO: id lookup table, this is very inefficent
for (const auto& [c_it, id_it] : msc.cr.view<Contact::Components::ID>().each()) {
if (id == id_it.data) {
h.emplace_or_replace<Message::Components::ContactFrom>(c_it);
return true;
}
}
// TODO: should we really return false if the contact is unknown??
return false;
}
template<>
bool MessageSerializerCallbacks::component_get_json<Message::Components::ContactTo>(MessageSerializerCallbacks& 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 MessageSerializerCallbacks::component_emplace_or_replace_json<Message::Components::ContactTo>(MessageSerializerCallbacks& 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;
}
const auto id = static_cast<std::vector<uint8_t>>(j);
// TODO: id lookup table, this is very inefficent
for (const auto& [c_it, id_it] : msc.cr.view<Contact::Components::ID>().each()) {
if (id == id_it.data) {
h.emplace_or_replace<Message::Components::ContactTo>(c_it);
return true;
}
}
// TODO: should we really return false if the contact is unknown??
return false;
}

View File

@ -0,0 +1,85 @@
#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 MessageSerializerCallbacks {
using Registry = Message3Registry;
using Handle = Message3Handle;
Contact3Registry& cr;
// nlohmann
// json/msgpack
using serialize_json_fn = bool(*)(MessageSerializerCallbacks& msc, const Handle h, nlohmann::json& out);
entt::dense_map<entt::id_type, serialize_json_fn> _serl_json;
using deserialize_json_fn = bool(*)(MessageSerializerCallbacks& msc, Handle h, const nlohmann::json& in);
entt::dense_map<entt::id_type, deserialize_json_fn> _deserl_json;
template<typename T>
static bool component_get_json(MessageSerializerCallbacks&, 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(MessageSerializerCallbacks&, 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 registerSerializerJson(serialize_json_fn fn, const entt::type_info& type_info) {
_serl_json[type_info.hash()] = fn;
}
template<typename CompType>
void registerSerializerJson(
serialize_json_fn fn = component_get_json<CompType>,
const entt::type_info& type_info = entt::type_id<CompType>()
) {
registerSerializerJson(fn, type_info);
}
void registerDeSerializerJson(deserialize_json_fn fn, const entt::type_info& type_info) {
_deserl_json[type_info.hash()] = fn;
}
template<typename CompType>
void registerDeSerializerJson(
deserialize_json_fn fn = component_emplace_or_replace_json<CompType>,
const entt::type_info& type_info = entt::type_id<CompType>()
) {
registerDeSerializerJson(fn, type_info);
}
};
// fwd
namespace Message::Components {
struct ContactFrom;
struct ContactTo;
}
// make specializations known
template<>
bool MessageSerializerCallbacks::component_get_json<Message::Components::ContactFrom>(MessageSerializerCallbacks& msc, const Handle h, nlohmann::json& j);
template<>
bool MessageSerializerCallbacks::component_emplace_or_replace_json<Message::Components::ContactFrom>(MessageSerializerCallbacks& msc, Handle h, const nlohmann::json& j);
template<>
bool MessageSerializerCallbacks::component_get_json<Message::Components::ContactTo>(MessageSerializerCallbacks& msc, const Handle h, nlohmann::json& j);
template<>
bool MessageSerializerCallbacks::component_emplace_or_replace_json<Message::Components::ContactTo>(MessageSerializerCallbacks& msc, Handle h, const nlohmann::json& j);