-
-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
68 changed files
with
1,096 additions
and
1,114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
project(serialization) | ||
|
||
include(${CMAKE_SOURCE_DIR}/cmake/apply_default_settings.cmake) | ||
|
||
file(GLOB serialization_SRC "include/*.h" "src/*.cpp" "src/*.h") | ||
add_library(serialization STATIC ${serialization_SRC}) | ||
target_include_directories(serialization PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) | ||
target_include_directories(serialization PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src) | ||
|
||
apply_default_settings(TARGETS serialization) | ||
|
||
find_package(slikenet CONFIG REQUIRED) | ||
target_link_libraries(serialization PUBLIC SLikeNet) | ||
|
||
find_package(simdjson CONFIG REQUIRED) | ||
target_link_libraries(serialization PUBLIC simdjson::simdjson) | ||
|
||
find_path(JSON_INCLUDE_DIR NAMES json.hpp PATH_SUFFIXES nlohmann) | ||
get_filename_component(JSON_INCLUDE_DIR ${JSON_INCLUDE_DIR} DIRECTORY) | ||
target_include_directories(serialization PUBLIC ${JSON_INCLUDE_DIR}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
list(APPEND CMAKEPROJ_PROJECTS serialization) | ||
set(CMAKEPROJ_PRIORITY_serialization 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#pragma once | ||
#include "concepts/Concepts.h" | ||
#include <optional> | ||
#include <slikenet/BitStream.h> | ||
#include <stdexcept> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "../impl/BitStreamUtil.h" | ||
#include "../impl/BitStreamUtil.ipp" | ||
|
||
#include <spdlog/spdlog.h> | ||
|
||
class BitStreamInputArchive | ||
{ | ||
public: | ||
explicit BitStreamInputArchive(SLNet::BitStream& bitStream) | ||
: bs(bitStream) | ||
{ | ||
} | ||
|
||
template <IntegralConstant T> | ||
BitStreamInputArchive& Serialize(const char* key, T&) | ||
{ | ||
// Compile time constant. Do nothing | ||
// Maybe worth adding equality check | ||
bs.IgnoreBytes(sizeof(typename T::value_type)); | ||
// spdlog::info("!!! deserialized integral constant {}", key); | ||
return *this; | ||
} | ||
|
||
template <StringLike T> | ||
BitStreamInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value.clear(); | ||
|
||
uint32_t n = 0; | ||
Serialize("size", n); | ||
|
||
// TODO: check n before resizing, so that we don't allocate a huge vector | ||
for (size_t i = 0; i < n; ++i) { | ||
typename T::value_type element; | ||
Serialize("element", element); | ||
value.push_back(element); | ||
} | ||
return *this; | ||
} | ||
|
||
// Specialization for std::array | ||
template <typename T, std::size_t N> | ||
BitStreamInputArchive& Serialize(const char* key, std::array<T, N>& value) | ||
{ | ||
for (size_t i = 0; i < N; ++i) { | ||
Serialize("element", value[i]); | ||
} | ||
return *this; | ||
} | ||
|
||
template <ContainerLike T> | ||
BitStreamInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value.clear(); | ||
|
||
uint32_t n = 0; | ||
Serialize("size", n); | ||
|
||
// TODO: check n before resizing, so that we don't allocate a huge vector | ||
for (size_t i = 0; i < n; ++i) { | ||
typename T::value_type element; | ||
Serialize("element", element); | ||
value.push_back(element); | ||
} | ||
return *this; | ||
} | ||
|
||
template <Optional T> | ||
BitStreamInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
bool hasValue = false; | ||
Serialize("hasValue", hasValue); | ||
if (hasValue) { | ||
typename T::value_type actualValue; | ||
Serialize("value", actualValue); | ||
value = actualValue; | ||
} else { | ||
value = std::nullopt; | ||
} | ||
return *this; | ||
} | ||
|
||
template <Arithmetic T> | ||
BitStreamInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
SerializationUtil::ReadFromBitStream(bs, value); | ||
// spdlog::info("!!! deserialized arithmetic {} {}", key, value); | ||
return *this; | ||
} | ||
|
||
template <NoneOfTheAbove T> | ||
BitStreamInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value.Serialize(*this); | ||
// spdlog::info("!!! deserialized none of the above {}", key); | ||
return *this; | ||
} | ||
|
||
SLNet::BitStream& bs; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#pragma once | ||
#include "concepts/Concepts.h" | ||
#include <optional> | ||
#include <slikenet/BitStream.h> | ||
#include <stdexcept> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "../impl/BitStreamUtil.h" | ||
#include "../impl/BitStreamUtil.ipp" | ||
|
||
#include <spdlog/spdlog.h> | ||
|
||
class BitStreamOutputArchive | ||
{ | ||
public: | ||
explicit BitStreamOutputArchive(SLNet::BitStream& bitStream) | ||
: bs(bitStream) | ||
{ | ||
} | ||
|
||
template <IntegralConstant T> | ||
BitStreamOutputArchive& Serialize(const char* key, T& value) | ||
{ | ||
using ValueType = typename T::value_type; | ||
auto actualValue = static_cast<ValueType>(value); | ||
SerializationUtil::WriteToBitStream(bs, actualValue); | ||
// spdlog::info("!!! serialized integral constant {} {}", key, | ||
// static_cast<int>(static_cast<char>(value))); | ||
return *this; | ||
} | ||
|
||
template <StringLike T> | ||
BitStreamOutputArchive& Serialize(const char* key, T& value) | ||
{ | ||
uint32_t n = static_cast<uint32_t>(value.size()); | ||
Serialize("size", n); | ||
|
||
for (size_t i = 0; i < n; ++i) { | ||
Serialize("element", value[i]); | ||
} | ||
return *this; | ||
} | ||
|
||
// Specialization for std::array | ||
template <typename T, std::size_t N> | ||
BitStreamOutputArchive& Serialize(const char* key, std::array<T, N>& value) | ||
{ | ||
for (size_t i = 0; i < N; ++i) { | ||
Serialize("element", value[i]); | ||
} | ||
return *this; | ||
} | ||
|
||
template <ContainerLike T> | ||
BitStreamOutputArchive& Serialize(const char* key, T& value) | ||
{ | ||
uint32_t n = static_cast<uint32_t>(value.size()); | ||
Serialize("size", n); | ||
|
||
for (size_t i = 0; i < n; ++i) { | ||
Serialize("element", value[i]); | ||
} | ||
return *this; | ||
} | ||
|
||
template <Optional T> | ||
BitStreamOutputArchive& Serialize(const char* key, T& value) | ||
{ | ||
bool hasValue = value.has_value(); | ||
Serialize("hasValue", hasValue); | ||
if (hasValue) { | ||
typename T::value_type& actualValue = *value; | ||
Serialize("value", actualValue); | ||
} | ||
return *this; | ||
} | ||
|
||
template <Arithmetic T> | ||
BitStreamOutputArchive& Serialize(const char* key, T& value) | ||
{ | ||
SerializationUtil::WriteToBitStream(bs, value); | ||
// spdlog::info("!!! serialized arithmetic {} {}", key, value); | ||
return *this; | ||
} | ||
|
||
template <NoneOfTheAbove T> | ||
BitStreamOutputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value.Serialize(*this); | ||
// spdlog::info("!!! serialized none of the above {}"); | ||
return *this; | ||
} | ||
|
||
SLNet::BitStream& bs; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#pragma once | ||
#include "concepts/Concepts.h" | ||
#include <nlohmann/json.hpp> | ||
#include <optional> | ||
#include <stdexcept> | ||
#include <string> | ||
#include <vector> | ||
|
||
class JsonInputArchive | ||
{ | ||
public: | ||
explicit JsonInputArchive(const nlohmann::json& json) | ||
: j(json) | ||
{ | ||
} | ||
|
||
template <IntegralConstant T> | ||
JsonInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
// Compile time constant. Do nothing | ||
// Maybe worth adding equality check | ||
return *this; | ||
} | ||
|
||
template <StringLike T> | ||
JsonInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value = j.at(key).get<std::string>(); | ||
return *this; | ||
} | ||
|
||
// Specialization for std::array | ||
template <typename T, std::size_t N> | ||
JsonInputArchive& Serialize(const char* key, std::array<T, N>& value) | ||
{ | ||
const auto& arr = j.at(key); | ||
if (arr.size() != N) { | ||
throw std::runtime_error( | ||
"JSON array size does not match std::array size."); | ||
} | ||
|
||
nlohmann::json childArchiveInput = nlohmann::json::object(); | ||
for (size_t i = 0; i < N; ++i) { | ||
childArchiveInput["element"] = arr.at(i); | ||
JsonInputArchive childArchive(childArchiveInput); | ||
childArchive.Serialize("element", value[i]); | ||
} | ||
return *this; | ||
} | ||
|
||
template <ContainerLike T> | ||
JsonInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value.clear(); | ||
|
||
const auto& arr = j.at(key); | ||
nlohmann::json childArchiveInput = nlohmann::json::object(); | ||
for (auto& elementJson : arr) { | ||
typename T::value_type element; | ||
childArchiveInput["element"] = elementJson; | ||
JsonInputArchive childArchive(childArchiveInput); | ||
childArchive.Serialize("element", element); | ||
value.insert(value.end(), element); | ||
} | ||
return *this; | ||
} | ||
|
||
template <Optional T> | ||
JsonInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
auto it = j.find(key); | ||
if (it != j.end() && !it->is_null()) { | ||
typename T::value_type actualValue; | ||
Serialize(key, actualValue); | ||
value = actualValue; | ||
} else { | ||
value = std::nullopt; | ||
} | ||
return *this; | ||
} | ||
|
||
template <Arithmetic T> | ||
JsonInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
value = j.at(key).get<T>(); | ||
return *this; | ||
} | ||
|
||
template <NoneOfTheAbove T> | ||
JsonInputArchive& Serialize(const char* key, T& value) | ||
{ | ||
const auto& obj = j.at(key); | ||
JsonInputArchive childArchive(obj); | ||
value.Serialize(childArchive); | ||
return *this; | ||
} | ||
|
||
private: | ||
const nlohmann::json& j; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#pragma once | ||
#include "concepts/Concepts.h" | ||
#include <nlohmann/json.hpp> | ||
#include <vector> | ||
|
||
class JsonOutputArchive | ||
{ | ||
public: | ||
template <IntegralConstant T> | ||
JsonOutputArchive& Serialize(const char* key, const T& value) | ||
{ | ||
j[key] = T::value; | ||
return *this; | ||
} | ||
|
||
template <StringLike T> | ||
JsonOutputArchive& Serialize(const char* key, const T& value) | ||
{ | ||
j[key] = value; | ||
return *this; | ||
} | ||
|
||
template <ContainerLike T> | ||
JsonOutputArchive& Serialize(const char* key, const T& value) | ||
{ | ||
nlohmann::json arr = nlohmann::json::array(); | ||
for (auto& element : value) { | ||
JsonOutputArchive childArchive; | ||
childArchive.Serialize("element", element); | ||
arr.push_back(childArchive.j["element"]); | ||
} | ||
j[key] = arr; | ||
return *this; | ||
} | ||
|
||
template <Optional T> | ||
JsonOutputArchive& Serialize(const char* key, const T& value) | ||
{ | ||
if (value.has_value()) { | ||
Serialize(key, *value); | ||
} else { | ||
// enable this if you want to serialize nulls | ||
// j[key] = nlohmann::json{}; | ||
} | ||
return *this; | ||
} | ||
|
||
template <Arithmetic T> | ||
JsonOutputArchive& Serialize(const char* key, const T& value) | ||
{ | ||
j[key] = value; | ||
return *this; | ||
} | ||
|
||
template <NoneOfTheAbove T> | ||
JsonOutputArchive& Serialize(const char* key, const T& value) | ||
{ | ||
nlohmann::json arr = nlohmann::json::object(); | ||
|
||
JsonOutputArchive childArchive; | ||
const_cast<T&>(value).Serialize(childArchive); | ||
|
||
j[key] = childArchive.j; | ||
return *this; | ||
} | ||
|
||
nlohmann::json j = nlohmann::json::object(); | ||
}; |
Oops, something went wrong.