From ef5e7811baaece8f14b1cb2b9398250131bcd537 Mon Sep 17 00:00:00 2001 From: Joel McKenzie Date: Fri, 18 Jul 2025 18:00:36 +0200 Subject: [PATCH 1/2] Allow using `rfl::AddTagsToVariants` with rfl::Generic and same-name structs The first one was the main reason for this change; the second one was a result of applying the change. Added tests for both. The issue was that both `std::vector` and `rfl::Object` were getting the type name 'Generic', which caused a compiler error due to duplicated field names. This will slightly increase the size of serialized formats when using the AddTagsToVariants, but it seems like a worthwhile change. --- .../rfl/parsing/VariantAlternativeWrapper.hpp | 2 +- tests/json/test_add_tag_to_rfl_variant.cpp | 4 +- tests/json/test_add_tag_to_variant.cpp | 47 ++++++++++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/include/rfl/parsing/VariantAlternativeWrapper.hpp b/include/rfl/parsing/VariantAlternativeWrapper.hpp index 924b711f..b55b292b 100644 --- a/include/rfl/parsing/VariantAlternativeWrapper.hpp +++ b/include/rfl/parsing/VariantAlternativeWrapper.hpp @@ -28,7 +28,7 @@ consteval auto make_tag() { return typename T::Tag(); } else { return Literal< - internal::remove_namespaces()>()>(); + internal::get_type_name()>(); } } diff --git a/tests/json/test_add_tag_to_rfl_variant.cpp b/tests/json/test_add_tag_to_rfl_variant.cpp index 265f72bb..061fde0c 100644 --- a/tests/json/test_add_tag_to_rfl_variant.cpp +++ b/tests/json/test_add_tag_to_rfl_variant.cpp @@ -1,9 +1,7 @@ #include -#include #include #include #include -#include #include #include "write_and_read.hpp" @@ -34,6 +32,6 @@ TEST(json, test_add_tag_to_rfl_variant) { write_and_read( vec, - R"([{"button_pressed_t":{}},{"button_released_t":{"button":4}},{"key_pressed":{"key":99}},{"int":3}])"); + R"([{"test_add_tag_to_rfl_variant::button_pressed_t":{}},{"test_add_tag_to_rfl_variant::button_released_t":{"button":4}},{"key_pressed":{"key":99}},{"int":3}])"); } } // namespace test_add_tag_to_rfl_variant diff --git a/tests/json/test_add_tag_to_variant.cpp b/tests/json/test_add_tag_to_variant.cpp index 5ce9a953..59a6bd12 100644 --- a/tests/json/test_add_tag_to_variant.cpp +++ b/tests/json/test_add_tag_to_variant.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -10,6 +9,8 @@ namespace test_add_tag_to_variant { +// test 1 -> normal behaviour + struct button_pressed_t {}; struct button_released_t {}; @@ -22,12 +23,54 @@ struct key_pressed_t { using my_event_type_t = std::variant; +// test 2 -> 'Generic' within a struct like this cannot be read/written +// due to the underlying `std::variant` holding two fields with name 'Generic' +// once 'remove_namespaces' is applied to the type name extraction (which is removed) +// in the MR this test is added +struct APIResult { + rfl::Generic result; +}; +struct APIError { + rfl::Generic error; +}; + +using APICallOutput = rfl::Variant; + +// test 3 -> two structs with the same name in different namespaces should still +// be serializable + +namespace Result { +struct Message { + std::string result; +}; +} // namespace Result + +namespace Error { +struct Message { + std::string error; + int error_id; +}; +}; // namespace Error + +using Messages = std::variant; + TEST(json, test_add_tag_to_variant) { const auto vec = std::vector( {button_pressed_t{}, button_released_t{}, key_pressed_t{'c'}, 3}); write_and_read( vec, - R"([{"button_pressed_t":{}},{"button_released_t":{}},{"key_pressed":{"key":99}},{"int":3}])"); + R"([{"test_add_tag_to_variant::button_pressed_t":{}},{"test_add_tag_to_variant::button_released_t":{}},{"key_pressed":{"key":99}},{"int":3}])"); +} + +TEST(json, test_add_tag_to_variant_with_generic) { + APICallOutput output = APIResult{"200"}; + write_and_read(output, + R"({"test_add_tag_to_variant::APIResult":{"result":{"std::string":"200"}}})"); +} +TEST(json, test_add_tag_to_variant_different_namespaces) { + Messages m = Error::Message{.error="an error", .error_id=2}; + write_and_read(m, + R"({"test_add_tag_to_variant::Error::Message":{"error":"an error","error_id":2}})"); } } // namespace test_add_tag_to_variant From db148fb9e9e8871f0e9038b78d25e5592888b56d Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sun, 7 Sep 2025 19:46:09 +0200 Subject: [PATCH 2/2] Handle std::string edge case --- include/rfl/parsing/VariantAlternativeWrapper.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/rfl/parsing/VariantAlternativeWrapper.hpp b/include/rfl/parsing/VariantAlternativeWrapper.hpp index b55b292b..926852d3 100644 --- a/include/rfl/parsing/VariantAlternativeWrapper.hpp +++ b/include/rfl/parsing/VariantAlternativeWrapper.hpp @@ -26,9 +26,12 @@ template consteval auto make_tag() { if constexpr (internal::has_tag_v) { return typename T::Tag(); + + } else if constexpr (std::is_same_v, std::string>) { + return Literal<"std::string">(); + } else { - return Literal< - internal::get_type_name()>(); + return Literal()>(); } }