give the message serializer its own repo

This commit is contained in:
Green Sky 2024-04-14 12:33:17 +02:00
commit 4039239c16
No known key found for this signature in database
6 changed files with 361 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@ -0,0 +1,26 @@
.vs/
*.o
*.swp
~*
*~
.idea/
cmake-build-debug/
cmake-build-debugandtest/
cmake-build-release/
*.stackdump
*.coredump
compile_commands.json
/build*
/result*
.clangd
.cache
.DS_Store
.AppleDouble
.LSOverride
CMakeLists.txt.user*
CMakeCache.txt
*.tox
imgui.ini

72
CMakeLists.txt Normal file
View File

@ -0,0 +1,72 @@
cmake_minimum_required(VERSION 3.24 FATAL_ERROR)
# cmake setup begin
project(solanaceae_message_serializer)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE ON)
else()
set(SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE OFF)
endif()
message("II SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE " ${SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE})
#option(SOLANACEAE_MESSAGE_SERIALIZER_BUILD_PLUGINS "Build the solanaceae_message_serializer plugins" ${SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE})
if (SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# defaulting to debug mode, if not specified
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
# setup my vim ycm :D
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# more paths
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
endif()
# external libs
add_subdirectory(./external EXCLUDE_FROM_ALL) # before increasing warn levels, sad :(
if (SOLANACEAE_MESSAGE_SERIALIZER_STANDALONE)
set(CMAKE_CXX_EXTENSIONS OFF)
# bump up warning levels appropriately for clang, gcc & msvc
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
add_compile_options(
-Wall -Wextra # Reasonable and standard
-Wpedantic # Warn if non-standard C++ is used
-Wunused # Warn on anything being unused
#-Wconversion # Warn on type conversions that may lose data
#-Wsign-conversion # Warn on sign conversions
-Wshadow # Warn if a variable declaration shadows one from a parent context
)
if (NOT WIN32)
#link_libraries(-fsanitize=address)
#link_libraries(-fsanitize=address,undefined)
#link_libraries(-fsanitize-address-use-after-scope)
#link_libraries(-fsanitize=undefined)
endif()
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
if (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
endif()
endif()
# cmake setup end
add_subdirectory(./src)
#if (SOLANACEAE_MESSAGE_SERIALIZER_BUILD_PLUGINS)
#add_subdirectory(./plugins)
#endif()

37
external/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.24 FATAL_ERROR)
include(FetchContent)
if (NOT TARGET solanaceae_util)
FetchContent_Declare(solanaceae_util
GIT_REPOSITORY https://github.com/Green-Sky/solanaceae_util.git
GIT_TAG master
)
FetchContent_MakeAvailable(solanaceae_util)
endif()
if (NOT TARGET solanaceae_contact)
FetchContent_Declare(solanaceae_contact
GIT_REPOSITORY https://github.com/Green-Sky/solanaceae_contact.git
GIT_TAG master
)
FetchContent_MakeAvailable(solanaceae_contact)
endif()
if (NOT TARGET solanaceae_message3)
FetchContent_Declare(solanaceae_message3
GIT_REPOSITORY https://github.com/Green-Sky/solanaceae_message3.git
GIT_TAG master
)
FetchContent_MakeAvailable(solanaceae_message3)
endif()
if (NOT TARGET nlohmann_json::nlohmann_json)
FetchContent_Declare(json
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
URL_HASH SHA256=d6c65aca6b1ed68e7a182f4757257b107ae403032760ed6ef121c9d55e81757d
EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(json)
endif()

19
src/CMakeLists.txt Normal file
View 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
)
########################################

View 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;
}

View 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);