From 4589aea723f7a0eb81db48bbda266e8a2b63a40b Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Thu, 29 Aug 2024 22:34:01 +0800 Subject: [PATCH 1/9] feat: to string support in mirror any --- .../Source/Common/Include/Common/Concepts.h | 2 + .../Source/Common/Include/Common/Math/Box.h | 16 +- .../Source/Common/Include/Common/Math/Color.h | 35 ++++ .../Source/Common/Include/Common/Math/Half.h | 21 +++ .../Common/Include/Common/Math/Matrix.h | 17 +- .../Common/Include/Common/Math/Projection.h | 36 +++- .../Common/Include/Common/Math/Quaternion.h | 42 ++++- .../Source/Common/Include/Common/Math/Rect.h | 16 +- .../Common/Include/Common/Math/Sphere.h | 18 +- .../Common/Include/Common/Math/Transform.h | 19 ++- .../Common/Include/Common/Math/Vector.h | 24 ++- .../Source/Common/Include/Common/Math/View.h | 15 +- .../Common/Include/Common/Serialization.h | 5 +- Engine/Source/Common/Include/Common/String.h | 161 ++++++++++++++++++ Engine/Source/Common/Src/Serialization.cpp | 36 ++-- Engine/Source/Common/Test/StringTest.cpp | 27 +++ Engine/Source/Mirror/Include/Mirror/Meta.h | 4 + Engine/Source/Mirror/Include/Mirror/Mirror.h | 13 +- Engine/Source/Mirror/Src/Mirror.cpp | 5 + Engine/Source/Mirror/Test/AnyTest.cpp | 5 + 20 files changed, 489 insertions(+), 28 deletions(-) diff --git a/Engine/Source/Common/Include/Common/Concepts.h b/Engine/Source/Common/Include/Common/Concepts.h index 7e79f34c..7c284f43 100644 --- a/Engine/Source/Common/Include/Common/Concepts.h +++ b/Engine/Source/Common/Include/Common/Concepts.h @@ -12,6 +12,8 @@ namespace Common { template concept CppSigned = std::is_signed_v; template concept CppUnsigned = std::is_unsigned_v; template concept CppArithmetic = std::is_arithmetic_v; + template concept CppBool = std::is_same_v; + template concept CppArithmeticNonBool = CppArithmetic && !CppBool; template concept CppClass = std::is_class_v; template concept CppVoid = std::is_void_v; template concept CppUnion = std::is_union_v; diff --git a/Engine/Source/Common/Include/Common/Math/Box.h b/Engine/Source/Common/Include/Common/Math/Box.h index 2d78f8cf..9e437561 100644 --- a/Engine/Source/Common/Include/Common/Math/Box.h +++ b/Engine/Source/Common/Include/Common/Math/Box.h @@ -6,6 +6,7 @@ #include #include +#include namespace Common { template @@ -52,7 +53,7 @@ namespace Common { } namespace Common { // NOLINT - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -78,6 +79,19 @@ namespace Common { // NOLINT return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Box& inValue) + { + return fmt::format( + "{min={}, max={}}", + StringConverter>::ToString(inValue.min), + StringConverter>::ToString(inValue.max)); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Color.h b/Engine/Source/Common/Include/Common/Math/Color.h index 98107cd8..ad6d68c5 100644 --- a/Engine/Source/Common/Include/Common/Math/Color.h +++ b/Engine/Source/Common/Include/Common/Math/Color.h @@ -7,6 +7,7 @@ #include #include +#include namespace Common { struct Color; @@ -123,4 +124,38 @@ namespace Common { return true; } }; + + template <> + struct StringConverter { + static constexpr auto convertible = true; + + static std::string ToString(const Color& inValue) + { + return fmt::format( + "{}r={}, g={}, b={}, a={}{}", + "{", + StringConverter::ToString(inValue.r), + StringConverter::ToString(inValue.g), + StringConverter::ToString(inValue.b), + StringConverter::ToString(inValue.a), + "}"); + } + }; + + template <> + struct StringConverter { + static constexpr auto convertible = true; + + static std::string ToString(const LinearColor& inValue) + { + return fmt::format( + "{}r={}, g={}, b={}, a={}{}", + "{", + StringConverter::ToString(inValue.r), + StringConverter::ToString(inValue.g), + StringConverter::ToString(inValue.b), + StringConverter::ToString(inValue.a), + "}"); + } + }; } diff --git a/Engine/Source/Common/Include/Common/Math/Half.h b/Engine/Source/Common/Include/Common/Math/Half.h index 882bbd92..ced96a41 100644 --- a/Engine/Source/Common/Include/Common/Math/Half.h +++ b/Engine/Source/Common/Include/Common/Math/Half.h @@ -10,6 +10,7 @@ #include #include +#include namespace Common { template concept ValidEndian = E == std::endian::little || E == std::endian::big; @@ -126,6 +127,26 @@ namespace Common { return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Internal::FullFloat& inValue) + { + return StringConverter::ToString(inValue.value); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const HalfFloat& inValue) + { + return StringConverter::ToString(inValue.AsFloat()); + } + }; } namespace Common::Internal { diff --git a/Engine/Source/Common/Include/Common/Math/Matrix.h b/Engine/Source/Common/Include/Common/Math/Matrix.h index a7cbeb9d..8263298b 100644 --- a/Engine/Source/Common/Include/Common/Math/Matrix.h +++ b/Engine/Source/Common/Include/Common/Math/Matrix.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -301,7 +302,7 @@ namespace Common { } namespace Common { // NOLINT - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -329,6 +330,20 @@ namespace Common { // NOLINT return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Mat& inValue) + { + return fmt::format("{row0={}, row1={}, row2={}, row3={}}", + StringConverter>::ToString(inValue.Row(0)), + StringConverter>::ToString(inValue.Row(1)), + StringConverter>::ToString(inValue.Row(2)), + StringConverter>::ToString(inValue.Row(3))); + } + }; } namespace Common::Internal { diff --git a/Engine/Source/Common/Include/Common/Math/Projection.h b/Engine/Source/Common/Include/Common/Math/Projection.h index d9516cf5..b89bfa96 100644 --- a/Engine/Source/Common/Include/Common/Math/Projection.h +++ b/Engine/Source/Common/Include/Common/Math/Projection.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace Common { template @@ -52,7 +53,7 @@ namespace Common { } namespace Common { - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -83,7 +84,7 @@ namespace Common { } }; - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -115,6 +116,37 @@ namespace Common { return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const ReversedZOrthogonalProjection& inValue) + { + return fmt::format( + "{width={}, height={}, near={}, far={}}", + StringConverter::ToString(inValue.width), + StringConverter::ToString(inValue.height), + StringConverter::ToString(inValue.nearPlane), + StringConverter>::ToString(inValue.farPlane)); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const ReversedZPerspectiveProjection& inValue) + { + return fmt::format( + "{fov={}, width={}, height={}, near={}, far={}}", + StringConverter::ToString(inValue.fov), + StringConverter::ToString(inValue.width), + StringConverter::ToString(inValue.height), + StringConverter::ToString(inValue.nearPlane), + StringConverter>::ToString(inValue.farPlane)); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Quaternion.h b/Engine/Source/Common/Include/Common/Math/Quaternion.h index 4771d1eb..97f41438 100644 --- a/Engine/Source/Common/Include/Common/Math/Quaternion.h +++ b/Engine/Source/Common/Include/Common/Math/Quaternion.h @@ -7,6 +7,7 @@ #include #include #include +#include namespace Common { template struct Angle; @@ -120,7 +121,7 @@ namespace Common { } namespace Common { - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -145,7 +146,7 @@ namespace Common { } }; - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -170,7 +171,7 @@ namespace Common { } }; - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -200,6 +201,41 @@ namespace Common { return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Angle& inValue) + { + return fmt::format("a{}", StringConverter::ToString(inValue.value)); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Radian& inValue) + { + return StringConverter::ToString(inValue.value); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Quaternion& inValue) + { + return fmt::format( + "({}, {}, {}, {})", + StringConverter::ToString(inValue.x), + StringConverter::ToString(inValue.y), + StringConverter::ToString(inValue.z), + StringConverter::ToString(inValue.w)); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Rect.h b/Engine/Source/Common/Include/Common/Math/Rect.h index 3cc846f6..8c3acda1 100644 --- a/Engine/Source/Common/Include/Common/Math/Rect.h +++ b/Engine/Source/Common/Include/Common/Math/Rect.h @@ -6,6 +6,7 @@ #include #include +#include namespace Common { template @@ -50,7 +51,7 @@ namespace Common { } namespace Common { - template + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -76,6 +77,19 @@ namespace Common { return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Rect& inValue) + { + return fmt::format( + "{min={}, max={}}", + StringConverter>::ToString(inValue.min), + StringConverter>::ToString(inValue.max)); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Sphere.h b/Engine/Source/Common/Include/Common/Math/Sphere.h index f08b5ad1..13b0fcb4 100644 --- a/Engine/Source/Common/Include/Common/Math/Sphere.h +++ b/Engine/Source/Common/Include/Common/Math/Sphere.h @@ -6,6 +6,7 @@ #include #include +#include namespace Common { template @@ -37,8 +38,8 @@ namespace Common { using DSphere = Sphere; } -namespace Common { // NOLINT - template +namespace Common { + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -64,6 +65,19 @@ namespace Common { // NOLINT return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Sphere& inValue) + { + return fmt::format( + "{center={}, radius={}}", + StringConverter>::Convert(inValue.center), + StringConverter::Convert(inValue.radius)); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Transform.h b/Engine/Source/Common/Include/Common/Math/Transform.h index e6c19fa2..39b284f1 100644 --- a/Engine/Source/Common/Include/Common/Math/Transform.h +++ b/Engine/Source/Common/Include/Common/Math/Transform.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace Common { template @@ -65,8 +66,8 @@ namespace Common { using DTransform = Transform; } -namespace Common { // NOLINT - template +namespace Common { + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -94,6 +95,20 @@ namespace Common { // NOLINT return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Transform& inValue) + { + return fmt::format( + "{scale={}, rotation={}, translation={}}", + StringConverter>::ToString(inValue.scale), + StringConverter>::ToString(inValue.rotation), + StringConverter>::ToString(inValue.translation)); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Vector.h b/Engine/Source/Common/Include/Common/Math/Vector.h index e5675dcd..84faf790 100644 --- a/Engine/Source/Common/Include/Common/Math/Vector.h +++ b/Engine/Source/Common/Include/Common/Math/Vector.h @@ -9,6 +9,7 @@ #include #include +#include namespace Common::Internal { template @@ -212,8 +213,8 @@ namespace Common::Internal { }; } -namespace Common { // NOLINT - template +namespace Common { + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -242,6 +243,25 @@ namespace Common { // NOLINT return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const Vec& inValue) + { + std::stringstream stream; + stream << "("; + for (auto i = 0; i < L; i++) { + stream << inValue.data[i]; + if (i != L - 1) { + stream << ", "; + } + } + stream << ")"; + return stream.str(); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/View.h b/Engine/Source/Common/Include/Common/Math/View.h index 19dd1b74..361c0751 100644 --- a/Engine/Source/Common/Include/Common/Math/View.h +++ b/Engine/Source/Common/Include/Common/Math/View.h @@ -6,6 +6,7 @@ #include #include +#include namespace Common { template @@ -27,8 +28,8 @@ namespace Common { using DViewTransform = ViewTransform; } -namespace Common { // NOLINT - template +namespace Common { + template struct Serializer> { static constexpr bool serializable = true; static constexpr uint32_t typeId @@ -52,6 +53,16 @@ namespace Common { // NOLINT return true; } }; + + template + struct StringConverter> { + static constexpr auto convertible = false; + + static std::string ToString(const ViewTransform& inValue) + { + return StringConverter>::ToString(inValue); + } + }; } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Serialization.h b/Engine/Source/Common/Include/Common/Serialization.h index c786f1d5..1e1e58ea 100644 --- a/Engine/Source/Common/Include/Common/Serialization.h +++ b/Engine/Source/Common/Include/Common/Serialization.h @@ -44,6 +44,7 @@ namespace Common { explicit BinaryFileSerializeStream(const std::string& inFileName); ~BinaryFileSerializeStream() override; void Write(const void* data, size_t size) override; + void Close(); private: std::ofstream file; @@ -55,6 +56,7 @@ namespace Common { explicit BinaryFileDeserializeStream(const std::string& inFileName); ~BinaryFileDeserializeStream() override; void Read(void* data, size_t size) override; + void Close(); private: std::ifstream file; @@ -84,7 +86,6 @@ namespace Common { const std::vector& bytes; }; - // TODO maybe there is a better way to do this ? template struct Serializer { static constexpr bool serializable = false; @@ -118,6 +119,8 @@ namespace Common { return typeId == Serializer::typeId; } }; + + // TODO to json object support } #define IMPL_BASIC_TYPE_SERIALIZER(typeName) \ diff --git a/Engine/Source/Common/Include/Common/String.h b/Engine/Source/Common/Include/Common/String.h index d8b04a92..c41946c0 100644 --- a/Engine/Source/Common/Include/Common/String.h +++ b/Engine/Source/Common/Include/Common/String.h @@ -6,10 +6,17 @@ #include #include +#include +#include +#include +#include #define FMT_HEADER_ONLY 1 #include +#include +#include + namespace Common { class StringUtils { public: @@ -26,4 +33,158 @@ namespace Common { static std::string AfterLast(const std::string& src, const std::string& split); static std::string BeforeLast(const std::string& src, const std::string& split); }; + + template + struct StringConverter { + static constexpr auto convertible = false; + + static std::string ToString(const T& inValue) + { + Unimplement(); + return ""; + } + }; + + template concept StringConvertible = StringConverter::convertible; + template std::string ToString(const T& inValue); +} + +namespace Common { + template + std::string ToString(const T& inValue) + { + if constexpr (StringConvertible) { + return StringConverter::ToString(inValue); + } else { + QuickFailWithReason("maybe you forget to specific string cast to your type ?"); + return ""; + } + } + + template <> + struct StringConverter { + static constexpr auto convertible = true; + + static std::string ToString(const bool& inValue) + { + return inValue ? "true" : "false"; + } + }; + + template + struct StringConverter { + static constexpr auto convertible = true; + + static std::string ToString(const T& inValue) + { + return std::to_string(inValue); + } + }; + + template <> + struct StringConverter { + static constexpr auto convertible = true; + + static std::string ToString(const std::string& inValue) + { + return inValue; + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const std::optional& inValue) + { + return inValue.has_value() + ? StringConverter::ToString(inValue.value()) + : "nullopt"; + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const std::pair& inValue) + { + return fmt::format( + "{}: {}", + StringConverter::ToString(inValue.first), + StringConverter::ToString(inValue.second)); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const std::vector& inValue) + { + std::stringstream stream; + stream << "("; + for (auto i = 0; i < inValue.size(); i++) { + stream << StringConverter::ToString(inValue[i]); + if (i != inValue.size() - 1) { + stream << ", "; + } + } + stream << ")"; + return stream.str(); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const std::unordered_set& inValue) + { + std::vector temp; + temp.reserve(inValue.size()); + for (auto iter = inValue.begin(); iter != inValue.end(); ++iter) { + temp.emplace_back(&*iter); + } + + std::stringstream stream; + stream << "("; + for (auto i = 0; i < temp.size(); i++) { + stream << StringConverter::ToString(*temp[i]); + if (i != temp.size() - 1) { + stream << ", "; + } + } + stream << ")"; + return stream.str(); + } + }; + + template + struct StringConverter> { + static constexpr auto convertible = true; + + static std::string ToString(const std::unordered_map& inValue) + { + std::vector> temp; + temp.reserve(inValue.size()); + for (auto iter = inValue.begin(); iter != inValue.end(); ++iter) { + temp.emplace_back(std::make_pair(&iter->first, &iter->second)); + } + + std::stringstream stream; + stream << "{"; + for (auto i = 0; i < temp.size(); i++) { + stream << fmt::format( + "{}: {}", + StringConverter::ToString(*temp[i].first), + StringConverter::ToString(*temp[i].second)); + if (i != temp.size() - 1) { + stream << ", "; + } + } + stream << "}"; + return stream.str(); + } + }; } diff --git a/Engine/Source/Common/Src/Serialization.cpp b/Engine/Source/Common/Src/Serialization.cpp index ba77f5cf..8f5b4030 100644 --- a/Engine/Source/Common/Src/Serialization.cpp +++ b/Engine/Source/Common/Src/Serialization.cpp @@ -26,11 +26,7 @@ namespace Common { BinaryFileSerializeStream::~BinaryFileSerializeStream() { - try { - file.close(); - } catch (const std::exception&) { - QuickFail(); - } + Close(); } void BinaryFileSerializeStream::Write(const void* data, const size_t size) @@ -38,6 +34,18 @@ namespace Common { file.write(static_cast(data), static_cast(size)); } + void BinaryFileSerializeStream::Close() + { + if (!file.is_open()) { + return; + } + try { + file.close(); + } catch (const std::exception&) { + QuickFail(); + } + } + BinaryFileDeserializeStream::BinaryFileDeserializeStream(const std::string& inFileName) : file(inFileName, std::ios::binary) { @@ -45,11 +53,7 @@ namespace Common { BinaryFileDeserializeStream::~BinaryFileDeserializeStream() { - try { - file.close(); - } catch (const std::exception&) { - QuickFail(); - } + Close(); } void BinaryFileDeserializeStream::Read(void* data, const size_t size) @@ -57,6 +61,18 @@ namespace Common { file.read(static_cast(data), static_cast(size)); } + void BinaryFileDeserializeStream::Close() + { + if (!file.is_open()) { + return; + } + try { + file.close(); + } catch (const std::exception&) { + QuickFail(); + } + } + ByteSerializeStream::ByteSerializeStream(std::vector& inBytes, const size_t pointerBegin) : pointer(pointerBegin) , bytes(inBytes) diff --git a/Engine/Source/Common/Test/StringTest.cpp b/Engine/Source/Common/Test/StringTest.cpp index aa10bf47..0da48c1e 100644 --- a/Engine/Source/Common/Test/StringTest.cpp +++ b/Engine/Source/Common/Test/StringTest.cpp @@ -104,3 +104,30 @@ TEST(StringUtilsTest, BeforeLastTest) ASSERT_EQ(StringUtils::BeforeLast("Hello, World", ", "), "Hello"); ASSERT_EQ(StringUtils::BeforeLast("12, 34, 56", ", "), "12, 34"); } + +TEST(StringUtilsTest, ToStringTest) +{ + ASSERT_EQ(Common::ToString(true), "true"); + ASSERT_EQ(Common::ToString(false), "false"); + ASSERT_EQ(Common::ToString(1), "1"); + + const std::string v0 = "1"; + ASSERT_EQ(Common::ToString(v0), "1"); + + std::optional v1 {}; + ASSERT_EQ(Common::ToString(v1), "nullopt"); + v1 = 1; + ASSERT_EQ(Common::ToString(v1), "1"); + + const std::pair v2 = { 1, false }; // NOLINT + ASSERT_EQ(Common::ToString(v2), "1: false"); + + const std::vector v3 = { 1, 2, 3 }; + ASSERT_EQ(Common::ToString(v3), "(1, 2, 3)"); + + const std::unordered_set v4 = { 1, 2, 3 }; + ASSERT_EQ(Common::ToString(v4), "(1, 2, 3)"); + + const std::unordered_map v5 = { { 1, false }, { 2, true } }; + ASSERT_EQ(Common::ToString(v5), "{1: false, 2: true}"); +} diff --git a/Engine/Source/Mirror/Include/Mirror/Meta.h b/Engine/Source/Mirror/Include/Mirror/Meta.h index 212b3f3e..9cb105dc 100644 --- a/Engine/Source/Mirror/Include/Mirror/Meta.h +++ b/Engine/Source/Mirror/Include/Mirror/Meta.h @@ -18,6 +18,10 @@ #define ECtor(...) #endif +namespace Mirror { + class Class; +} + #define EClassBody(className) \ private: \ static int _mirrorRegistry; \ diff --git a/Engine/Source/Mirror/Include/Mirror/Mirror.h b/Engine/Source/Mirror/Include/Mirror/Mirror.h index 2acbb16d..ea2f6f36 100644 --- a/Engine/Source/Mirror/Include/Mirror/Mirror.h +++ b/Engine/Source/Mirror/Include/Mirror/Mirror.h @@ -90,6 +90,7 @@ namespace Mirror { using GetPtrFunc = Any(void*); using GetConstPtrFunc = Any(const void*); using DerefFunc = Any(const void*); + using ToStringFunc = std::string(const void*); template static void Detor(void* inThis) noexcept; template static void CopyConstruct(void* inThis, const void* inOther); @@ -105,6 +106,7 @@ namespace Mirror { template static Any GetPtr(void* inThis); template static Any GetConstPtr(const void* inThis); template static Any Deref(const void* inThis); + template static std::string ToString(const void* inThis); DetorFunc* detor; CopyConstructFunc* copyConstruct; @@ -120,6 +122,7 @@ namespace Mirror { GetPtrFunc* getPtr; GetConstPtrFunc* getConstPtr; DerefFunc* deref; + ToStringFunc* toString; }; template @@ -137,7 +140,8 @@ namespace Mirror { &AnyRtti::GetAddConstPointerType, &AnyRtti::GetPtr, &AnyRtti::GetConstPtr, - &AnyRtti::Deref + &AnyRtti::Deref, + &AnyRtti::ToString }; class MIRROR_API Any { @@ -197,6 +201,7 @@ namespace Mirror { Mirror::TypeId TypeId() const; void Reset(); bool Empty() const; + std::string ToString() const; // always return original ptr and size, even policy is ref void* Data() const; @@ -929,6 +934,12 @@ namespace Mirror { } } + template + std::string AnyRtti::ToString(const void* inThis) + { + return Common::ToString(*static_cast(inThis)); + } + template Any::Any(T&& inValue) { diff --git a/Engine/Source/Mirror/Src/Mirror.cpp b/Engine/Source/Mirror/Src/Mirror.cpp index 118b73f9..26ea2a95 100644 --- a/Engine/Source/Mirror/Src/Mirror.cpp +++ b/Engine/Source/Mirror/Src/Mirror.cpp @@ -388,6 +388,11 @@ namespace Mirror { return rtti == nullptr; } + std::string Any::ToString() const + { + return Empty() ? "" : rtti->toString(Data()); + } + void* Any::Data() const { return IsRef() ? std::get(info).Ptr() : std::get(info).Ptr(); diff --git a/Engine/Source/Mirror/Test/AnyTest.cpp b/Engine/Source/Mirror/Test/AnyTest.cpp index ec5da122..4227b4a2 100644 --- a/Engine/Source/Mirror/Test/AnyTest.cpp +++ b/Engine/Source/Mirror/Test/AnyTest.cpp @@ -1183,3 +1183,8 @@ TEST(AnyTest, OperatorEqualTest) void Foo() const {} }; } + +TEST(AnyTest, ToStringTest) +{ + // TODO +} From ebaf42087615a09b30918e94594e8fa5c5e020d8 Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Fri, 30 Aug 2024 18:57:54 +0800 Subject: [PATCH 2/9] feat: add rapidjson to 3rd libraries --- Engine/Source/Common/CMakeLists.txt | 2 +- README.md | 1 + ThirdParty/CMakeLists.txt | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Engine/Source/Common/CMakeLists.txt b/Engine/Source/Common/CMakeLists.txt index 7b5cbd20..8c54a3e3 100644 --- a/Engine/Source/Common/CMakeLists.txt +++ b/Engine/Source/Common/CMakeLists.txt @@ -4,7 +4,7 @@ AddLibrary( TYPE STATIC SRC ${SOURCES} PUBLIC_INC Include - LIB debugbreak cityhash taskflow fmt-lib + LIB debugbreak cityhash taskflow fmt-lib rapidjson ) file(GLOB TEST_SOURCES Test/*.cpp) diff --git a/README.md b/README.md index 3656d3b1..e6c8c741 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ Thanks all those following projects: * [assimp](https://github.com/assimp/assimp) * [VulkanMemoryAllocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) * [Qt6](https://www.qt.io/product/qt6) +* [rapidjson](https://github.com/Tencent/rapidjson) # Sponsor diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index 9f664ab0..9183d343 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -233,3 +233,12 @@ Find3rdPackage( $/6.5.2/msvc2019_64/bin/Qt6Gui$,d,>.dll $/6.5.2/msvc2019_64/bin/Qt6Widgets$,d,>.dll ) + +# rapidjson +Add3rdHeaderOnlyPackage( + NAME rapidjson + PLATFORM All + VERSION 1.1.0 + HASH c19c92601374a161b0355ccb73f02b31076c70d4446e5ad53c8b80263a9c900c + INCLUDE $/include +) From 7c399d1790dcaf605816690272f7a480446b696f Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sat, 31 Aug 2024 00:37:18 +0800 Subject: [PATCH 3/9] feat: json serializer basic --- .../Source/Common/Include/Common/Math/Box.h | 2 ++ .../Source/Common/Include/Common/Math/Color.h | 2 ++ .../Source/Common/Include/Common/Math/Half.h | 2 ++ .../Common/Include/Common/Math/Matrix.h | 2 ++ .../Common/Include/Common/Math/Projection.h | 2 ++ .../Common/Include/Common/Math/Quaternion.h | 2 ++ .../Source/Common/Include/Common/Math/Rect.h | 2 ++ .../Common/Include/Common/Math/Sphere.h | 2 ++ .../Common/Include/Common/Math/Transform.h | 2 ++ .../Common/Include/Common/Math/Vector.h | 2 ++ .../Source/Common/Include/Common/Math/View.h | 2 ++ .../Common/Include/Common/Serialization.h | 21 ++++++++++++++++++- Engine/Source/Mirror/Include/Mirror/Mirror.h | 1 + 13 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Engine/Source/Common/Include/Common/Math/Box.h b/Engine/Source/Common/Include/Common/Math/Box.h index 9e437561..4d545a5e 100644 --- a/Engine/Source/Common/Include/Common/Math/Box.h +++ b/Engine/Source/Common/Include/Common/Math/Box.h @@ -92,6 +92,8 @@ namespace Common { // NOLINT StringConverter>::ToString(inValue.max)); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Color.h b/Engine/Source/Common/Include/Common/Math/Color.h index ad6d68c5..f5650654 100644 --- a/Engine/Source/Common/Include/Common/Math/Color.h +++ b/Engine/Source/Common/Include/Common/Math/Color.h @@ -158,4 +158,6 @@ namespace Common { "}"); } }; + + // TODO json converter impl } diff --git a/Engine/Source/Common/Include/Common/Math/Half.h b/Engine/Source/Common/Include/Common/Math/Half.h index ced96a41..e935bdfa 100644 --- a/Engine/Source/Common/Include/Common/Math/Half.h +++ b/Engine/Source/Common/Include/Common/Math/Half.h @@ -147,6 +147,8 @@ namespace Common { return StringConverter::ToString(inValue.AsFloat()); } }; + + // TODO json converter impl } namespace Common::Internal { diff --git a/Engine/Source/Common/Include/Common/Math/Matrix.h b/Engine/Source/Common/Include/Common/Math/Matrix.h index 8263298b..54525672 100644 --- a/Engine/Source/Common/Include/Common/Math/Matrix.h +++ b/Engine/Source/Common/Include/Common/Math/Matrix.h @@ -344,6 +344,8 @@ namespace Common { // NOLINT StringConverter>::ToString(inValue.Row(3))); } }; + + // TODO json converter impl } namespace Common::Internal { diff --git a/Engine/Source/Common/Include/Common/Math/Projection.h b/Engine/Source/Common/Include/Common/Math/Projection.h index b89bfa96..2a9ce48e 100644 --- a/Engine/Source/Common/Include/Common/Math/Projection.h +++ b/Engine/Source/Common/Include/Common/Math/Projection.h @@ -147,6 +147,8 @@ namespace Common { StringConverter>::ToString(inValue.farPlane)); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Quaternion.h b/Engine/Source/Common/Include/Common/Math/Quaternion.h index 97f41438..8e551b99 100644 --- a/Engine/Source/Common/Include/Common/Math/Quaternion.h +++ b/Engine/Source/Common/Include/Common/Math/Quaternion.h @@ -236,6 +236,8 @@ namespace Common { StringConverter::ToString(inValue.w)); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Rect.h b/Engine/Source/Common/Include/Common/Math/Rect.h index 8c3acda1..ee4e608a 100644 --- a/Engine/Source/Common/Include/Common/Math/Rect.h +++ b/Engine/Source/Common/Include/Common/Math/Rect.h @@ -90,6 +90,8 @@ namespace Common { StringConverter>::ToString(inValue.max)); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Sphere.h b/Engine/Source/Common/Include/Common/Math/Sphere.h index 13b0fcb4..a31ea0bd 100644 --- a/Engine/Source/Common/Include/Common/Math/Sphere.h +++ b/Engine/Source/Common/Include/Common/Math/Sphere.h @@ -78,6 +78,8 @@ namespace Common { StringConverter::Convert(inValue.radius)); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Transform.h b/Engine/Source/Common/Include/Common/Math/Transform.h index 39b284f1..dc6a1148 100644 --- a/Engine/Source/Common/Include/Common/Math/Transform.h +++ b/Engine/Source/Common/Include/Common/Math/Transform.h @@ -109,6 +109,8 @@ namespace Common { StringConverter>::ToString(inValue.translation)); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/Vector.h b/Engine/Source/Common/Include/Common/Math/Vector.h index 84faf790..5ad7319a 100644 --- a/Engine/Source/Common/Include/Common/Math/Vector.h +++ b/Engine/Source/Common/Include/Common/Math/Vector.h @@ -262,6 +262,8 @@ namespace Common { return stream.str(); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Math/View.h b/Engine/Source/Common/Include/Common/Math/View.h index 361c0751..c3a41e67 100644 --- a/Engine/Source/Common/Include/Common/Math/View.h +++ b/Engine/Source/Common/Include/Common/Math/View.h @@ -63,6 +63,8 @@ namespace Common { return StringConverter>::ToString(inValue); } }; + + // TODO json converter impl } namespace Common { diff --git a/Engine/Source/Common/Include/Common/Serialization.h b/Engine/Source/Common/Include/Common/Serialization.h index 1e1e58ea..a6bb828c 100644 --- a/Engine/Source/Common/Include/Common/Serialization.h +++ b/Engine/Source/Common/Include/Common/Serialization.h @@ -11,6 +11,8 @@ #include #include +#include + #include #include #include @@ -120,7 +122,22 @@ namespace Common { } }; - // TODO to json object support + template + struct JsonValueConverter { + static constexpr auto convertible = false; + + static rapidjson::Value ToJsonValue(const T& inValue) + { + QuickFailWithReason("your type is not support convert to json value"); + return {}; + } + }; + + template rapidjson::Value ToJsonValue(const T& inValue) + { + // TODO + return {}; + } } #define IMPL_BASIC_TYPE_SERIALIZER(typeName) \ @@ -374,4 +391,6 @@ namespace Common { return true; } }; + + // TODO json converter impl } diff --git a/Engine/Source/Mirror/Include/Mirror/Mirror.h b/Engine/Source/Mirror/Include/Mirror/Mirror.h index ea2f6f36..151deaa5 100644 --- a/Engine/Source/Mirror/Include/Mirror/Mirror.h +++ b/Engine/Source/Mirror/Include/Mirror/Mirror.h @@ -202,6 +202,7 @@ namespace Mirror { void Reset(); bool Empty() const; std::string ToString() const; + // TODO rapidjson::Value ToJsonValue() const; // always return original ptr and size, even policy is ref void* Data() const; From 6d35144cfd6ba578bd66ad34436c829ed58fd9cf Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sun, 1 Sep 2024 18:34:41 +0800 Subject: [PATCH 4/9] feat: empty serializer --- .../Common/Include/Common/Serialization.h | 18 ++++++++++++++++++ Engine/Source/Common/Src/Serialization.cpp | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Engine/Source/Common/Include/Common/Serialization.h b/Engine/Source/Common/Include/Common/Serialization.h index a6bb828c..28be27df 100644 --- a/Engine/Source/Common/Include/Common/Serialization.h +++ b/Engine/Source/Common/Include/Common/Serialization.h @@ -40,6 +40,24 @@ namespace Common { DeserializeStream(); }; + class EmptySerializeStream final : public SerializeStream { + public: + NonCopyable(EmptySerializeStream) + EmptySerializeStream(); + ~EmptySerializeStream() override; + + void Write(const void* data, size_t size) override; + }; + + class EmptyDeserializeStream final : public DeserializeStream { + public: + NonCopyable(EmptyDeserializeStream) + EmptyDeserializeStream(); + ~EmptyDeserializeStream() override; + + void Read(void* data, size_t size) override; + }; + class BinaryFileSerializeStream final : public SerializeStream { public: NonCopyable(BinaryFileSerializeStream) diff --git a/Engine/Source/Common/Src/Serialization.cpp b/Engine/Source/Common/Src/Serialization.cpp index 8f5b4030..ff1d8e79 100644 --- a/Engine/Source/Common/Src/Serialization.cpp +++ b/Engine/Source/Common/Src/Serialization.cpp @@ -15,6 +15,18 @@ namespace Common { DeserializeStream::~DeserializeStream() = default; + EmptySerializeStream::EmptySerializeStream() = default; + + EmptySerializeStream::~EmptySerializeStream() = default; + + void EmptySerializeStream::Write(const void* data, size_t size) {} + + EmptyDeserializeStream::EmptyDeserializeStream() = default; + + EmptyDeserializeStream::~EmptyDeserializeStream() = default; + + void EmptyDeserializeStream::Read(void* data, size_t size) {} + BinaryFileSerializeStream::BinaryFileSerializeStream(const std::string& inFileName) { if (const auto parent_path = std::filesystem::path(inFileName).parent_path(); From 83ef64613d474d806157a9998bd0a4ddb3ffe3c6 Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sun, 1 Sep 2024 18:43:15 +0800 Subject: [PATCH 5/9] feat: optimize to string templates code --- .../Source/Common/Include/Common/Math/Box.h | 2 -- .../Source/Common/Include/Common/Math/Color.h | 4 --- .../Source/Common/Include/Common/Math/Half.h | 4 --- .../Common/Include/Common/Math/Matrix.h | 2 -- .../Common/Include/Common/Math/Projection.h | 4 --- .../Common/Include/Common/Math/Quaternion.h | 6 ---- .../Source/Common/Include/Common/Math/Rect.h | 2 -- .../Common/Include/Common/Math/Sphere.h | 2 -- .../Common/Include/Common/Math/Transform.h | 2 -- .../Common/Include/Common/Math/Vector.h | 2 -- Engine/Source/Common/Include/Common/String.h | 30 ++----------------- 11 files changed, 2 insertions(+), 58 deletions(-) diff --git a/Engine/Source/Common/Include/Common/Math/Box.h b/Engine/Source/Common/Include/Common/Math/Box.h index 4d545a5e..ca4169d0 100644 --- a/Engine/Source/Common/Include/Common/Math/Box.h +++ b/Engine/Source/Common/Include/Common/Math/Box.h @@ -82,8 +82,6 @@ namespace Common { // NOLINT template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Box& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Color.h b/Engine/Source/Common/Include/Common/Math/Color.h index f5650654..046bd5a4 100644 --- a/Engine/Source/Common/Include/Common/Math/Color.h +++ b/Engine/Source/Common/Include/Common/Math/Color.h @@ -127,8 +127,6 @@ namespace Common { template <> struct StringConverter { - static constexpr auto convertible = true; - static std::string ToString(const Color& inValue) { return fmt::format( @@ -144,8 +142,6 @@ namespace Common { template <> struct StringConverter { - static constexpr auto convertible = true; - static std::string ToString(const LinearColor& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Half.h b/Engine/Source/Common/Include/Common/Math/Half.h index e935bdfa..0425c665 100644 --- a/Engine/Source/Common/Include/Common/Math/Half.h +++ b/Engine/Source/Common/Include/Common/Math/Half.h @@ -130,8 +130,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Internal::FullFloat& inValue) { return StringConverter::ToString(inValue.value); @@ -140,8 +138,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const HalfFloat& inValue) { return StringConverter::ToString(inValue.AsFloat()); diff --git a/Engine/Source/Common/Include/Common/Math/Matrix.h b/Engine/Source/Common/Include/Common/Math/Matrix.h index 54525672..01e13e27 100644 --- a/Engine/Source/Common/Include/Common/Math/Matrix.h +++ b/Engine/Source/Common/Include/Common/Math/Matrix.h @@ -333,8 +333,6 @@ namespace Common { // NOLINT template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Mat& inValue) { return fmt::format("{row0={}, row1={}, row2={}, row3={}}", diff --git a/Engine/Source/Common/Include/Common/Math/Projection.h b/Engine/Source/Common/Include/Common/Math/Projection.h index 2a9ce48e..136f5de9 100644 --- a/Engine/Source/Common/Include/Common/Math/Projection.h +++ b/Engine/Source/Common/Include/Common/Math/Projection.h @@ -119,8 +119,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const ReversedZOrthogonalProjection& inValue) { return fmt::format( @@ -134,8 +132,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const ReversedZPerspectiveProjection& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Quaternion.h b/Engine/Source/Common/Include/Common/Math/Quaternion.h index 8e551b99..b3b9a019 100644 --- a/Engine/Source/Common/Include/Common/Math/Quaternion.h +++ b/Engine/Source/Common/Include/Common/Math/Quaternion.h @@ -204,8 +204,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Angle& inValue) { return fmt::format("a{}", StringConverter::ToString(inValue.value)); @@ -214,8 +212,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Radian& inValue) { return StringConverter::ToString(inValue.value); @@ -224,8 +220,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Quaternion& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Rect.h b/Engine/Source/Common/Include/Common/Math/Rect.h index ee4e608a..953c653a 100644 --- a/Engine/Source/Common/Include/Common/Math/Rect.h +++ b/Engine/Source/Common/Include/Common/Math/Rect.h @@ -80,8 +80,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Rect& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Sphere.h b/Engine/Source/Common/Include/Common/Math/Sphere.h index a31ea0bd..390ed43a 100644 --- a/Engine/Source/Common/Include/Common/Math/Sphere.h +++ b/Engine/Source/Common/Include/Common/Math/Sphere.h @@ -68,8 +68,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Sphere& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Transform.h b/Engine/Source/Common/Include/Common/Math/Transform.h index dc6a1148..58831f70 100644 --- a/Engine/Source/Common/Include/Common/Math/Transform.h +++ b/Engine/Source/Common/Include/Common/Math/Transform.h @@ -98,8 +98,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Transform& inValue) { return fmt::format( diff --git a/Engine/Source/Common/Include/Common/Math/Vector.h b/Engine/Source/Common/Include/Common/Math/Vector.h index 5ad7319a..feaf66b9 100644 --- a/Engine/Source/Common/Include/Common/Math/Vector.h +++ b/Engine/Source/Common/Include/Common/Math/Vector.h @@ -246,8 +246,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const Vec& inValue) { std::stringstream stream; diff --git a/Engine/Source/Common/Include/Common/String.h b/Engine/Source/Common/Include/Common/String.h index c41946c0..713b60a4 100644 --- a/Engine/Source/Common/Include/Common/String.h +++ b/Engine/Source/Common/Include/Common/String.h @@ -34,18 +34,8 @@ namespace Common { static std::string BeforeLast(const std::string& src, const std::string& split); }; - template - struct StringConverter { - static constexpr auto convertible = false; - - static std::string ToString(const T& inValue) - { - Unimplement(); - return ""; - } - }; - - template concept StringConvertible = StringConverter::convertible; + template struct StringConverter {}; + template concept StringConvertible = requires (T inValue) { { StringConverter::ToString(inValue) } -> std::convertible_to; }; template std::string ToString(const T& inValue); } @@ -63,8 +53,6 @@ namespace Common { template <> struct StringConverter { - static constexpr auto convertible = true; - static std::string ToString(const bool& inValue) { return inValue ? "true" : "false"; @@ -73,8 +61,6 @@ namespace Common { template struct StringConverter { - static constexpr auto convertible = true; - static std::string ToString(const T& inValue) { return std::to_string(inValue); @@ -83,8 +69,6 @@ namespace Common { template <> struct StringConverter { - static constexpr auto convertible = true; - static std::string ToString(const std::string& inValue) { return inValue; @@ -93,8 +77,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const std::optional& inValue) { return inValue.has_value() @@ -105,8 +87,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const std::pair& inValue) { return fmt::format( @@ -118,8 +98,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const std::vector& inValue) { std::stringstream stream; @@ -137,8 +115,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const std::unordered_set& inValue) { std::vector temp; @@ -162,8 +138,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = true; - static std::string ToString(const std::unordered_map& inValue) { std::vector> temp; From ce34031b964d04346c9d4b195d150536cf710d3c Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sun, 1 Sep 2024 19:00:57 +0800 Subject: [PATCH 6/9] feat: optimize serialization templates code --- .../Source/Common/Include/Common/Math/Box.h | 1 - .../Source/Common/Include/Common/Math/Color.h | 2 - .../Source/Common/Include/Common/Math/Half.h | 2 - .../Common/Include/Common/Math/Matrix.h | 1 - .../Common/Include/Common/Math/Projection.h | 2 - .../Common/Include/Common/Math/Quaternion.h | 3 - .../Source/Common/Include/Common/Math/Rect.h | 1 - .../Common/Include/Common/Math/Sphere.h | 1 - .../Common/Include/Common/Math/Transform.h | 1 - .../Common/Include/Common/Math/Vector.h | 1 - .../Source/Common/Include/Common/Math/View.h | 1 - .../Common/Include/Common/Serialization.h | 75 +++++++++---------- Engine/Source/Common/Src/Serialization.cpp | 12 --- Engine/Source/Core/Include/Core/Uri.h | 1 - .../Source/Mirror/Include/Mirror/Registry.h | 38 +++------- Engine/Source/Runtime/Include/Runtime/Asset.h | 2 - 16 files changed, 45 insertions(+), 99 deletions(-) diff --git a/Engine/Source/Common/Include/Common/Math/Box.h b/Engine/Source/Common/Include/Common/Math/Box.h index ca4169d0..3015bf07 100644 --- a/Engine/Source/Common/Include/Common/Math/Box.h +++ b/Engine/Source/Common/Include/Common/Math/Box.h @@ -55,7 +55,6 @@ namespace Common { namespace Common { // NOLINT template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Box") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Math/Color.h b/Engine/Source/Common/Include/Common/Math/Color.h index 046bd5a4..bcf7b2c6 100644 --- a/Engine/Source/Common/Include/Common/Math/Color.h +++ b/Engine/Source/Common/Include/Common/Math/Color.h @@ -69,7 +69,6 @@ namespace Common { namespace Common { template <> struct Serializer { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Color"); static void Serialize(SerializeStream& stream, const Color& value) @@ -98,7 +97,6 @@ namespace Common { template <> struct Serializer { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::LinearColor"); static void Serialize(SerializeStream& stream, const LinearColor& value) diff --git a/Engine/Source/Common/Include/Common/Math/Half.h b/Engine/Source/Common/Include/Common/Math/Half.h index 0425c665..af2f817e 100644 --- a/Engine/Source/Common/Include/Common/Math/Half.h +++ b/Engine/Source/Common/Include/Common/Math/Half.h @@ -84,7 +84,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Internal::FullFloat"); static void Serialize(SerializeStream& stream, const Internal::FullFloat& value) @@ -107,7 +106,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Internal::HalfFloat"); static void Serialize(SerializeStream& stream, const HalfFloat& value) diff --git a/Engine/Source/Common/Include/Common/Math/Matrix.h b/Engine/Source/Common/Include/Common/Math/Matrix.h index 01e13e27..d8a54b1b 100644 --- a/Engine/Source/Common/Include/Common/Math/Matrix.h +++ b/Engine/Source/Common/Include/Common/Math/Matrix.h @@ -304,7 +304,6 @@ namespace Common { namespace Common { // NOLINT template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Matrix") + Serializer::typeId + (R << 8) + C; diff --git a/Engine/Source/Common/Include/Common/Math/Projection.h b/Engine/Source/Common/Include/Common/Math/Projection.h index 136f5de9..2cee171c 100644 --- a/Engine/Source/Common/Include/Common/Math/Projection.h +++ b/Engine/Source/Common/Include/Common/Math/Projection.h @@ -55,7 +55,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::ReversedZOrthogonalProjection") + Serializer::typeId; @@ -86,7 +85,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::ReversedZPerspectiveProjection") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Math/Quaternion.h b/Engine/Source/Common/Include/Common/Math/Quaternion.h index b3b9a019..8813b652 100644 --- a/Engine/Source/Common/Include/Common/Math/Quaternion.h +++ b/Engine/Source/Common/Include/Common/Math/Quaternion.h @@ -123,7 +123,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Angle") + Serializer::typeId; @@ -148,7 +147,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Radian") + Serializer::typeId; @@ -173,7 +171,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Quaternion") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Math/Rect.h b/Engine/Source/Common/Include/Common/Math/Rect.h index 953c653a..229d8a7d 100644 --- a/Engine/Source/Common/Include/Common/Math/Rect.h +++ b/Engine/Source/Common/Include/Common/Math/Rect.h @@ -53,7 +53,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Rect") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Math/Sphere.h b/Engine/Source/Common/Include/Common/Math/Sphere.h index 390ed43a..69ae6cc0 100644 --- a/Engine/Source/Common/Include/Common/Math/Sphere.h +++ b/Engine/Source/Common/Include/Common/Math/Sphere.h @@ -41,7 +41,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Sphere") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Math/Transform.h b/Engine/Source/Common/Include/Common/Math/Transform.h index 58831f70..005888cd 100644 --- a/Engine/Source/Common/Include/Common/Math/Transform.h +++ b/Engine/Source/Common/Include/Common/Math/Transform.h @@ -69,7 +69,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::Transform") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Math/Vector.h b/Engine/Source/Common/Include/Common/Math/Vector.h index feaf66b9..8292e2bf 100644 --- a/Engine/Source/Common/Include/Common/Math/Vector.h +++ b/Engine/Source/Common/Include/Common/Math/Vector.h @@ -216,7 +216,6 @@ namespace Common::Internal { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = Common::HashUtils::StrCrc32("Common::Vector") + Serializer::typeId diff --git a/Engine/Source/Common/Include/Common/Math/View.h b/Engine/Source/Common/Include/Common/Math/View.h index c3a41e67..5a753bdc 100644 --- a/Engine/Source/Common/Include/Common/Math/View.h +++ b/Engine/Source/Common/Include/Common/Math/View.h @@ -31,7 +31,6 @@ namespace Common { namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Common::ViewTransform") + Serializer::typeId; diff --git a/Engine/Source/Common/Include/Common/Serialization.h b/Engine/Source/Common/Include/Common/Serialization.h index 28be27df..f6d7616c 100644 --- a/Engine/Source/Common/Include/Common/Serialization.h +++ b/Engine/Source/Common/Include/Common/Serialization.h @@ -40,24 +40,6 @@ namespace Common { DeserializeStream(); }; - class EmptySerializeStream final : public SerializeStream { - public: - NonCopyable(EmptySerializeStream) - EmptySerializeStream(); - ~EmptySerializeStream() override; - - void Write(const void* data, size_t size) override; - }; - - class EmptyDeserializeStream final : public DeserializeStream { - public: - NonCopyable(EmptyDeserializeStream) - EmptyDeserializeStream(); - ~EmptyDeserializeStream() override; - - void Read(void* data, size_t size) override; - }; - class BinaryFileSerializeStream final : public SerializeStream { public: NonCopyable(BinaryFileSerializeStream) @@ -107,23 +89,15 @@ namespace Common { }; template - struct Serializer { - static constexpr bool serializable = false; - - static void Serialize(SerializeStream&, const T&) - { - Unimplement(); - } + struct Serializer {}; - static bool Deserialize(DeserializeStream&, T&) - { - Unimplement(); - return false; - } + template concept Serializable = requires(T inValue, SerializeStream& serializeStream, DeserializeStream& deserializeStream) + { + { Serializer::typeId } -> std::convertible_to; + Serializer::Serialize(serializeStream, inValue); + Serializer::Deserialize(deserializeStream, inValue); }; - template concept Serializable = Serializer::serializable; - template struct TypeIdSerializer { static void Serialize(SerializeStream& stream) @@ -140,6 +114,26 @@ namespace Common { } }; + template + void Serialize(SerializeStream& inStream, const T& inValue) + { + if constexpr (Serializable) { + Serializer::Serialize(inStream, inValue); + } else { + QuickFailWithReason("your type is not support serialization"); + } + } + + template + void Deserialize(DeserializeStream& inStream, T& inValue) + { + if constexpr (Serializable) { + Serializer::Deserialize(inStream, inValue); + } else { + QuickFailWithReason("your type is not support serialization"); + } + } + template struct JsonValueConverter { static constexpr auto convertible = false; @@ -151,17 +145,22 @@ namespace Common { } }; + template concept JsonValueConvertible = requires(T inValue) { { JsonValueConverter::ToJsonValue(inValue) } -> std::convertible_to; }; + template rapidjson::Value ToJsonValue(const T& inValue) { - // TODO - return {}; + if constexpr (JsonValueConvertible) { + return JsonValueConverter::ToJsonValue(inValue); + } else { + QuickFailWithReason("your type is not support convert to json value"); + return {}; + } } } #define IMPL_BASIC_TYPE_SERIALIZER(typeName) \ template <> \ struct Serializer { \ - static constexpr bool serializable = true; \ static constexpr uint32_t typeId = Common::HashUtils::StrCrc32(#typeName); \ \ static void Serialize(SerializeStream& stream, const typeName& value) \ @@ -195,7 +194,6 @@ namespace Common { template <> struct Serializer { - static constexpr bool serializable = true; static constexpr uint32_t typeId = Common::HashUtils::StrCrc32("string"); static void Serialize(SerializeStream& stream, const std::string& value) @@ -223,7 +221,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("std::optional") + Serializer::typeId; @@ -261,7 +258,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("std::pair") + Serializer::typeId @@ -289,7 +285,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("std::vector") + Serializer::typeId; @@ -329,7 +324,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("std::unordered_set") + Serializer::typeId; @@ -369,7 +363,6 @@ namespace Common { template struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = Common::HashUtils::StrCrc32("std::unordered_map") + Serializer::typeId diff --git a/Engine/Source/Common/Src/Serialization.cpp b/Engine/Source/Common/Src/Serialization.cpp index ff1d8e79..8f5b4030 100644 --- a/Engine/Source/Common/Src/Serialization.cpp +++ b/Engine/Source/Common/Src/Serialization.cpp @@ -15,18 +15,6 @@ namespace Common { DeserializeStream::~DeserializeStream() = default; - EmptySerializeStream::EmptySerializeStream() = default; - - EmptySerializeStream::~EmptySerializeStream() = default; - - void EmptySerializeStream::Write(const void* data, size_t size) {} - - EmptyDeserializeStream::EmptyDeserializeStream() = default; - - EmptyDeserializeStream::~EmptyDeserializeStream() = default; - - void EmptyDeserializeStream::Read(void* data, size_t size) {} - BinaryFileSerializeStream::BinaryFileSerializeStream(const std::string& inFileName) { if (const auto parent_path = std::filesystem::path(inFileName).parent_path(); diff --git a/Engine/Source/Core/Include/Core/Uri.h b/Engine/Source/Core/Include/Core/Uri.h index ec217c29..1e67a3fa 100644 --- a/Engine/Source/Core/Include/Core/Uri.h +++ b/Engine/Source/Core/Include/Core/Uri.h @@ -65,7 +65,6 @@ namespace std { // NOLINT namespace Common { // NOLINT template <> struct Serializer { - static constexpr bool serializable = true; static constexpr uint32_t typeId = HashUtils::StrCrc32("Core::Uri"); static void Serialize(SerializeStream& stream, const Core::Uri& value) diff --git a/Engine/Source/Mirror/Include/Mirror/Registry.h b/Engine/Source/Mirror/Include/Mirror/Registry.h index 7d5a2f8e..d3e0a7ce 100644 --- a/Engine/Source/Mirror/Include/Mirror/Registry.h +++ b/Engine/Source/Mirror/Include/Mirror/Registry.h @@ -336,22 +336,14 @@ namespace Mirror { return { std::ref(object.As().*Ptr) }; }; params.serializer = [](Common::SerializeStream& stream, const Mirror::MemberVariable& variable, const Argument& object) -> void { - if constexpr (Common::Serializer::serializable) { - ValueType& value = variable.GetDyn(object).As(); - Common::Serializer::Serialize(stream, value); - } else { - Unimplement(); - } + ValueType& value = variable.GetDyn(object).As(); // NOLINT + Common::Serialize(stream, value); }; params.deserializer = [](Common::DeserializeStream& stream, const Mirror::MemberVariable& variable, const Argument& object) -> void { - if constexpr (Common::Serializer::serializable) { - ValueType value; - Common::Serializer::Deserialize(stream, value); - Any valueRef = std::ref(value); - variable.SetDyn(object, valueRef); - } else { - Unimplement(); - } + ValueType value; + Common::Deserialize(stream, value); + Any valueRef = std::ref(value); + variable.SetDyn(object, valueRef); }; return MetaDataRegistry::SetContext(&clazz.EmplaceMemberVariable(inId, std::move(params))); @@ -409,21 +401,13 @@ namespace Mirror { return { std::ref(*Ptr) }; }; params.serializer = [](Common::SerializeStream& stream, const Mirror::Variable& variable) -> void { - if constexpr (Common::Serializer::serializable) { - ValueType& value = variable.GetDyn().As(); - Common::Serializer::Serialize(stream, value); - } else { - Unimplement(); - } + ValueType& value = variable.GetDyn().As(); // NOLINT + Common::Serialize(stream, value); }; params.deserializer = [](Common::DeserializeStream& stream, const Mirror::Variable& variable) -> void { - if constexpr (Common::Serializer::serializable) { - ValueType value; - Common::Serializer::Deserialize(stream, value); - variable.Set(value); - } else { - Unimplement(); - } + ValueType value; + Common::Deserialize(stream, value); + variable.Set(value); }; return SetContext(&globalScope.EmplaceVariable(inId, std::move(params))); diff --git a/Engine/Source/Runtime/Include/Runtime/Asset.h b/Engine/Source/Runtime/Include/Runtime/Asset.h index c61c2b3b..755bf186 100644 --- a/Engine/Source/Runtime/Include/Runtime/Asset.h +++ b/Engine/Source/Runtime/Include/Runtime/Asset.h @@ -414,7 +414,6 @@ namespace Runtime { namespace Common { template A> struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = Common::HashUtils::StrCrc32("Runtime::AssetRef"); static void Serialize(SerializeStream& stream, const Runtime::AssetRef& value) @@ -438,7 +437,6 @@ namespace Common { template A> struct Serializer> { - static constexpr bool serializable = true; static constexpr uint32_t typeId = Common::HashUtils::StrCrc32("Runtime::SoftAssetRef"); static void Serialize(SerializeStream& stream, const Runtime::SoftAssetRef& value) From 21d4c0d148c7a243a5ae080095e2b91cc7108a70 Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sun, 1 Sep 2024 19:09:19 +0800 Subject: [PATCH 7/9] feat: json serialization support --- .../Source/Common/Include/Common/Concepts.h | 3 +- .../Source/Common/Include/Common/Math/View.h | 2 - .../Common/Include/Common/Serialization.h | 285 +++++++++++++++++- .../Source/Common/Test/SerializationTest.cpp | 10 + Engine/Source/Mirror/Include/Mirror/Mirror.h | 5 + 5 files changed, 294 insertions(+), 11 deletions(-) diff --git a/Engine/Source/Common/Include/Common/Concepts.h b/Engine/Source/Common/Include/Common/Concepts.h index 7c284f43..02ae8d75 100644 --- a/Engine/Source/Common/Include/Common/Concepts.h +++ b/Engine/Source/Common/Include/Common/Concepts.h @@ -7,12 +7,13 @@ #include namespace Common { + template concept CppBool = std::is_same_v; template concept CppIntegral = std::is_integral_v; + template concept CppIntegralNonBool = CppIntegral && !CppBool; template concept CppFloatingPoint = std::is_floating_point_v; template concept CppSigned = std::is_signed_v; template concept CppUnsigned = std::is_unsigned_v; template concept CppArithmetic = std::is_arithmetic_v; - template concept CppBool = std::is_same_v; template concept CppArithmeticNonBool = CppArithmetic && !CppBool; template concept CppClass = std::is_class_v; template concept CppVoid = std::is_void_v; diff --git a/Engine/Source/Common/Include/Common/Math/View.h b/Engine/Source/Common/Include/Common/Math/View.h index 5a753bdc..59223330 100644 --- a/Engine/Source/Common/Include/Common/Math/View.h +++ b/Engine/Source/Common/Include/Common/Math/View.h @@ -55,8 +55,6 @@ namespace Common { template struct StringConverter> { - static constexpr auto convertible = false; - static std::string ToString(const ViewTransform& inValue) { return StringConverter>::ToString(inValue); diff --git a/Engine/Source/Common/Include/Common/Serialization.h b/Engine/Source/Common/Include/Common/Serialization.h index f6d7616c..e2892779 100644 --- a/Engine/Source/Common/Include/Common/Serialization.h +++ b/Engine/Source/Common/Include/Common/Serialization.h @@ -136,23 +136,37 @@ namespace Common { template struct JsonValueConverter { - static constexpr auto convertible = false; - - static rapidjson::Value ToJsonValue(const T& inValue) + static rapidjson::Value ToJsonValue(const T& inValue, rapidjson::Document::AllocatorType& inAllocator) { QuickFailWithReason("your type is not support convert to json value"); return {}; } }; - template concept JsonValueConvertible = requires(T inValue) { { JsonValueConverter::ToJsonValue(inValue) } -> std::convertible_to; }; + template concept JsonValueConvertible = requires(T inValue, rapidjson::Document::AllocatorType& inAllocator, const rapidjson::Value& inJsonValue) + { + { JsonValueConverter::ToJsonValue(inValue, inAllocator) } -> std::convertible_to; + { JsonValueConverter::FromJsonValue(inJsonValue) } -> std::same_as; + }; - template rapidjson::Value ToJsonValue(const T& inValue) + template + rapidjson::Value ToJsonValue(const T& inValue, rapidjson::Document::AllocatorType& inAllocator) { if constexpr (JsonValueConvertible) { - return JsonValueConverter::ToJsonValue(inValue); + return JsonValueConverter::ToJsonValue(inValue, inAllocator); } else { - QuickFailWithReason("your type is not support convert to json value"); + QuickFailWithReason("your type is not support json serialization"); + return {}; + } + } + + template + T FromJsonValue(const rapidjson::Value& inJsonValue) + { + if constexpr (JsonValueConvertible) { + return JsonValueConverter::FromJsonValue(inJsonValue); + } else { + QuickFailWithReason("your type is not support json serialization"); return {}; } } @@ -403,5 +417,260 @@ namespace Common { } }; - // TODO json converter impl + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const bool& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static bool FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetBool(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const int8_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static int8_t FromJsonValue(const rapidjson::Value& inValue) + { + return static_cast(inValue.GetInt()); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const uint8_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static uint8_t FromJsonValue(const rapidjson::Value& inValue) + { + return static_cast(inValue.GetUint()); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const int16_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static int16_t FromJsonValue(const rapidjson::Value& inValue) + { + return static_cast(inValue.GetInt()); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const uint16_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static uint16_t FromJsonValue(const rapidjson::Value& inValue) + { + return static_cast(inValue.GetUint()); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const int32_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static int32_t FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetInt(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const uint32_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static uint32_t FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetUint(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const int64_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static int64_t FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetInt64(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const uint64_t& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static uint64_t FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetUint64(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const float& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static float FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetFloat(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const double& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue); + } + + static double FromJsonValue(const rapidjson::Value& inValue) + { + return inValue.GetDouble(); + } + }; + + template <> + struct JsonValueConverter { + static rapidjson::Value ToJsonValue(const std::string& inValue, rapidjson::Document& inAllocator) + { + return rapidjson::Value(inValue.c_str(), inValue.length()); + } + + static std::string FromJsonValue(const rapidjson::Value& inValue) + { + return { inValue.GetString(), inValue.GetStringLength() }; + } + }; + + template + struct JsonValueConverter> { + static rapidjson::Value ToJsonValue(const std::optional& inValue, rapidjson::Document& inAllocator) + { + if (inValue.has_value()) { + return JsonValueConverter::ToJsonValue(inValue.value()); + } + return rapidjson::Value(rapidjson::kNullType); + } + + static std::optional FromJsonValue(const rapidjson::Value& inValue) + { + if (inValue.IsNull()) { + return {}; + } + return JsonValueConverter::FromJsonValue(inValue); + } + }; + + template + struct JsonValueConverter> { + static rapidjson::Value ToJsonValue(const std::pair& inValue, rapidjson::Document& inAllocator) + { + rapidjson::Value result(rapidjson::kObjectType); + result.AddMember("key", JsonValueConverter::ToJsonValue(inValue.first), inAllocator); + result.AddMember("value", JsonValueConverter::ToJsonValue(inValue.second), inAllocator); + return result; + } + + static std::pair FromJsonValue(const rapidjson::Value& inValue) + { + return { + JsonValueConverter::FromJsonValue(inValue["key"]), + JsonValueConverter::FromJsonValue(inValue["value"]) + }; + } + }; + + template + struct JsonValueConverter> { + static rapidjson::Value ToJsonValue(const std::vector& inValue, rapidjson::Document& inAllocator) + { + rapidjson::Value result(rapidjson::kArrayType); + for (const auto& element : inValue) { + result.PushBack(JsonValueConverter::ToJsonValue(element), inAllocator); + } + return result; + } + + static std::vector FromJsonValue(const rapidjson::Value& inValue) + { + std::vector result; + for (auto i = 0; i < inValue.Size(); i++) { + result.emplace_back(JsonValueConverter::FromJsonValue(inValue[i])); + } + return result; + } + }; + + template + struct JsonValueConverter> { + static rapidjson::Value ToJsonValue(const std::unordered_set& inValue, rapidjson::Document& inAllocator) + { + rapidjson::Value result(rapidjson::kArrayType); + for (const auto& element : inValue) { + result.PushBack(JsonValueConverter::ToJsonValue(element), inAllocator); + } + return result; + } + + static std::unordered_set FromJsonValue(const rapidjson::Value& inValue) + { + std::unordered_set result; + for (auto i = 0; i < inValue.Size(); i++) { + result.emplace(JsonValueConverter::FromJsonValue(inValue[i])); + } + return result; + } + }; + + template + struct JsonValueConverter> { + static rapidjson::Value ToJsonValue(const std::unordered_map& inValue, rapidjson::Document& inAllocator) + { + rapidjson::Value result(rapidjson::kArrayType); + for (const auto& pair : inValue) { + result.PushBack(JsonValueConverter>::ToJsonValue(pair), inAllocator); + } + return result; + } + + static std::unordered_map FromJsonValue(const rapidjson::Value& inValue) + { + std::unordered_map result; + for (auto i = 0; i < inValue.Size(); i++) { + result.emplace(JsonValueConverter>::FromJsonValue(inValue[i])); + } + return result; + } + }; } diff --git a/Engine/Source/Common/Test/SerializationTest.cpp b/Engine/Source/Common/Test/SerializationTest.cpp index 6145ce77..29449221 100644 --- a/Engine/Source/Common/Test/SerializationTest.cpp +++ b/Engine/Source/Common/Test/SerializationTest.cpp @@ -29,3 +29,13 @@ TEST(SerializationTest, FileStreamTest) ASSERT_EQ(value, 5); } } + +TEST(SerializationTest, SerializationTest) +{ + // TODO +} + +TEST(SerializationTest, JsonSerializeTest) +{ + // TODO +} diff --git a/Engine/Source/Mirror/Include/Mirror/Mirror.h b/Engine/Source/Mirror/Include/Mirror/Mirror.h index 151deaa5..1ca27f0b 100644 --- a/Engine/Source/Mirror/Include/Mirror/Mirror.h +++ b/Engine/Source/Mirror/Include/Mirror/Mirror.h @@ -340,6 +340,7 @@ namespace Mirror { Any GetDyn() const; void SerializeDyn(Common::SerializeStream& stream) const; void DeserializeDyn(Common::DeserializeStream& stream) const; + // TODO json support private: friend class GlobalRegistry; @@ -360,6 +361,7 @@ namespace Mirror { Getter getter; VariableSerializer serializer; VariableDeserializer deserializer; + // TODO json support }; explicit Variable(ConstructParams&& params); @@ -483,6 +485,7 @@ namespace Mirror { template Any Get(C&& object) const; template void Serialize(Common::SerializeStream& stream, C&& object) const; template void Deserialize(Common::DeserializeStream& stream, C&& object) const; + // TODO json support uint32_t SizeOf() const; const TypeInfo* GetTypeInfo() const; @@ -509,6 +512,7 @@ namespace Mirror { Getter getter; MemberVariableSerializer serializer; MemberVariableDeserializer deserializer; + // TODO json support }; explicit MemberVariable(ConstructParams&& params); @@ -648,6 +652,7 @@ namespace Mirror { Any NewDyn(const ArgumentList& arguments) const; void SerializeDyn(Common::SerializeStream& stream, const Argument& obj) const; void DeserailizeDyn(Common::DeserializeStream& stream, const Argument& obj) const; + // TODO json support private: static std::unordered_map typeToIdMap; From 4ebae8553bcce0a7cc039586c960c97bcf7ac988 Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sun, 1 Sep 2024 20:28:57 +0800 Subject: [PATCH 8/9] feat: add serialization test --- .../Source/Common/Test/SerializationTest.cpp | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/Engine/Source/Common/Test/SerializationTest.cpp b/Engine/Source/Common/Test/SerializationTest.cpp index 29449221..9f3fd8c0 100644 --- a/Engine/Source/Common/Test/SerializationTest.cpp +++ b/Engine/Source/Common/Test/SerializationTest.cpp @@ -3,17 +3,42 @@ // #include +#include #include - #include using namespace Common; +template +void PerformTypedSerializationTest(const T& inValue, const std::function& inCustomCompareFunc = {}) +{ + static std::filesystem::path fileName = "../Test/Generated/Common/SerializationTest.TypedSerializationTest"; + std::filesystem::create_directories(fileName.parent_path()); + + { + BinaryFileSerializeStream stream(fileName.string()); + Serialize(stream, inValue); + } + + { + T value; + BinaryFileDeserializeStream stream(fileName.string()); + Deserialize(stream, value); + + if (inCustomCompareFunc) { + ASSERT_TRUE(inCustomCompareFunc(inValue, value)); + } else { + ASSERT_EQ(inValue, value); + } + } +} + TEST(SerializationTest, FileStreamTest) { static std::filesystem::path fileName = "../Test/Generated/Common/SerializationTest.FileStreamTest.bin"; std::filesystem::create_directories(fileName.parent_path()); + { const uint32_t value = 5; // NOLINT @@ -30,9 +55,60 @@ TEST(SerializationTest, FileStreamTest) } } -TEST(SerializationTest, SerializationTest) +TEST(SerializationTest, TypedSerializationTest) { - // TODO + PerformTypedSerializationTest(false); + PerformTypedSerializationTest(true); + PerformTypedSerializationTest(-1); + PerformTypedSerializationTest(1); + PerformTypedSerializationTest(-2); + PerformTypedSerializationTest(2); + PerformTypedSerializationTest(-3); + PerformTypedSerializationTest(3); + PerformTypedSerializationTest(-4); + PerformTypedSerializationTest(4); + PerformTypedSerializationTest(5.0f); + PerformTypedSerializationTest(6.0); + PerformTypedSerializationTest("hello"); + PerformTypedSerializationTest>({}); + PerformTypedSerializationTest>(15); + PerformTypedSerializationTest>({ 1, false }); + PerformTypedSerializationTest>({ 1, 2, 3 }, [](const std::vector& inLhs, const std::vector& inRhs) -> bool { + if (inLhs.size() != inRhs.size()) { + return false; + } + for (auto i = 0; i < inLhs.size(); i++) { + if (inLhs[i] != inRhs[i]) { + return false; + } + } + return true; + }); + PerformTypedSerializationTest>({ 1, 2, 3 }, [](const std::unordered_set& inLhs, const std::unordered_set& inRhs) -> bool { + if (inLhs.size() != inRhs.size()) { + return false; + } + for (const auto& element : inLhs) { + if (!inRhs.contains(element)) { + return false; + } + } + return true; + }); + PerformTypedSerializationTest>({ { 1, false }, { 2, true } }, [](const std::unordered_map& inLhs, const std::unordered_map& inRhs) -> bool { + if (inLhs.size() != inRhs.size()) { + return false; + } + for (const auto& [key, value] : inLhs) { + if (!inRhs.contains(key)) { + return false; + } + if (inRhs.at(key) != value) { + return false; + } + } + return true; + }); } TEST(SerializationTest, JsonSerializeTest) From 7d7c27c51008f0a6e11790d39e01b6237cc69f9c Mon Sep 17 00:00:00 2001 From: John Kindem <461425614@qq.com> Date: Sun, 1 Sep 2024 20:49:10 +0800 Subject: [PATCH 9/9] refactor: update serialization interfaces --- .../Common/Include/Common/Serialization.h | 109 +++++++++--------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/Engine/Source/Common/Include/Common/Serialization.h b/Engine/Source/Common/Include/Common/Serialization.h index e2892779..87b26e51 100644 --- a/Engine/Source/Common/Include/Common/Serialization.h +++ b/Engine/Source/Common/Include/Common/Serialization.h @@ -88,9 +88,7 @@ namespace Common { const std::vector& bytes; }; - template - struct Serializer {}; - + template struct Serializer {}; template concept Serializable = requires(T inValue, SerializeStream& serializeStream, DeserializeStream& deserializeStream) { { Serializer::typeId } -> std::convertible_to; @@ -100,20 +98,61 @@ namespace Common { template struct TypeIdSerializer { - static void Serialize(SerializeStream& stream) - { - const uint32_t typeId = Serializer::typeId; - stream.Write(&typeId, sizeof(uint32_t)); - } + static void Serialize(SerializeStream& stream); + static bool Deserialize(DeserializeStream& stream); + }; - static bool Deserialize(DeserializeStream& stream) - { - uint32_t typeId; - stream.Read(&typeId, sizeof(uint32_t)); - return typeId == Serializer::typeId; - } + template void Serialize(SerializeStream& inStream, const T& inValue); + template void Deserialize(DeserializeStream& inStream, T& inValue); + + template struct JsonValueConverter {}; + template concept JsonValueConvertible = requires(T inValue, rapidjson::Document::AllocatorType& inAllocator, const rapidjson::Value& inJsonValue) + { + { JsonValueConverter::ToJsonValue(inValue, inAllocator) } -> std::convertible_to; + { JsonValueConverter::FromJsonValue(inJsonValue) } -> std::same_as; }; + template rapidjson::Value ToJsonValue(const T& inValue, rapidjson::Document::AllocatorType& inAllocator); + template T FromJsonValue(const rapidjson::Value& inJsonValue); +} + +#define IMPL_BASIC_TYPE_SERIALIZER(typeName) \ + template <> \ + struct Serializer { \ + static constexpr uint32_t typeId = HashUtils::StrCrc32(#typeName); \ + \ + static void Serialize(SerializeStream& stream, const typeName& value) \ + { \ + TypeIdSerializer::Serialize(stream); \ + stream.Write(&value, sizeof(typeName)); \ + } \ + \ + static bool Deserialize(DeserializeStream& stream, typeName& value) \ + { \ + if (!TypeIdSerializer::Deserialize(stream)) { \ + return false;\ + } \ + stream.Read(&value, sizeof(typeName)); \ + return true; \ + } \ + }; \ + +namespace Common { + template + void TypeIdSerializer::Serialize(SerializeStream& stream) + { + const uint32_t typeId = Serializer::typeId; + stream.Write(&typeId, sizeof(uint32_t)); + } + + template + bool TypeIdSerializer::Deserialize(DeserializeStream& stream) + { + uint32_t typeId; + stream.Read(&typeId, sizeof(uint32_t)); + return typeId == Serializer::typeId; + } + template void Serialize(SerializeStream& inStream, const T& inValue) { @@ -134,21 +173,6 @@ namespace Common { } } - template - struct JsonValueConverter { - static rapidjson::Value ToJsonValue(const T& inValue, rapidjson::Document::AllocatorType& inAllocator) - { - QuickFailWithReason("your type is not support convert to json value"); - return {}; - } - }; - - template concept JsonValueConvertible = requires(T inValue, rapidjson::Document::AllocatorType& inAllocator, const rapidjson::Value& inJsonValue) - { - { JsonValueConverter::ToJsonValue(inValue, inAllocator) } -> std::convertible_to; - { JsonValueConverter::FromJsonValue(inJsonValue) } -> std::same_as; - }; - template rapidjson::Value ToJsonValue(const T& inValue, rapidjson::Document::AllocatorType& inAllocator) { @@ -170,30 +194,7 @@ namespace Common { return {}; } } -} - -#define IMPL_BASIC_TYPE_SERIALIZER(typeName) \ - template <> \ - struct Serializer { \ - static constexpr uint32_t typeId = Common::HashUtils::StrCrc32(#typeName); \ - \ - static void Serialize(SerializeStream& stream, const typeName& value) \ - { \ - TypeIdSerializer::Serialize(stream); \ - stream.Write(&value, sizeof(typeName)); \ - } \ - \ - static bool Deserialize(DeserializeStream& stream, typeName& value) \ - { \ - if (!TypeIdSerializer::Deserialize(stream)) { \ - return false;\ - } \ - stream.Read(&value, sizeof(typeName)); \ - return true; \ - } \ - }; \ -namespace Common { IMPL_BASIC_TYPE_SERIALIZER(bool) IMPL_BASIC_TYPE_SERIALIZER(int8_t) IMPL_BASIC_TYPE_SERIALIZER(uint8_t) @@ -208,7 +209,7 @@ namespace Common { template <> struct Serializer { - static constexpr uint32_t typeId = Common::HashUtils::StrCrc32("string"); + static constexpr uint32_t typeId = HashUtils::StrCrc32("string"); static void Serialize(SerializeStream& stream, const std::string& value) { @@ -378,7 +379,7 @@ namespace Common { template struct Serializer> { static constexpr uint32_t typeId - = Common::HashUtils::StrCrc32("std::unordered_map") + = HashUtils::StrCrc32("std::unordered_map") + Serializer::typeId + Serializer::typeId;