From c6b354223907d973ffe844834d61d48fd6d03f6d Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sat, 28 Feb 2026 10:18:16 +0100 Subject: [PATCH 1/5] Added a test --- tests/xml/test_generic.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/xml/test_generic.cpp diff --git a/tests/xml/test_generic.cpp b/tests/xml/test_generic.cpp new file mode 100644 index 00000000..9116f12f --- /dev/null +++ b/tests/xml/test_generic.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +#include "write_and_read.hpp" + +namespace test_generic { + +TEST(xml, test_generic) { + rfl::Generic::Object cat; + cat["name"] = "Cachou"; + cat["colour"] = "black"; + cat["species"] = "cat"; + + const auto xml_string = rfl::xml::write<"cat">(cat); + + std::cout << xml_string << std::endl; + + const auto generic_cat = + rfl::xml::read>(xml_string); + + std::cout << rfl::xml::write<"cat">(generic_cat) << std::endl; +} +} // namespace test_generic From 4742c46cea3b1ac6c91c239a2a26bcb32450a975 Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sat, 28 Feb 2026 10:18:27 +0100 Subject: [PATCH 2/5] Stricter type checks for boolean --- include/rfl/xml/Reader.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/rfl/xml/Reader.hpp b/include/rfl/xml/Reader.hpp index fdbc5242..67f2c98d 100644 --- a/include/rfl/xml/Reader.hpp +++ b/include/rfl/xml/Reader.hpp @@ -85,7 +85,14 @@ struct Reader { return std::visit(get_value, _var.node_or_attribute_); } else if constexpr (std::is_same, bool>()) { - return std::visit(get_value, _var.node_or_attribute_) == "true"; + const auto val = std::visit(get_value, _var.node_or_attribute_); + if (val == "true" || val == "1") { + return true; + } else if (val == "false" || val == "0") { + return false; + } else { + return error("Could not cast '" + val + "' to boolean."); + } } else if constexpr (std::is_floating_point>()) { const auto str = std::visit(get_value, _var.node_or_attribute_); From edefe6f9a4617e7331831cfe139532c0865534be Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sat, 7 Mar 2026 15:54:16 +0100 Subject: [PATCH 3/5] Generics can only be written to XML, but you cannot read them --- include/rfl/xml/Parser.hpp | 48 +++++++++++++++++++++++++++++--------- include/rfl/xml/Reader.hpp | 7 +++--- tests/xml/test_generic.cpp | 14 ++++++----- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/include/rfl/xml/Parser.hpp b/include/rfl/xml/Parser.hpp index 2f2c4ca0..f04b7183 100644 --- a/include/rfl/xml/Parser.hpp +++ b/include/rfl/xml/Parser.hpp @@ -3,39 +3,65 @@ #include +#include "../Generic.hpp" +#include "../always_false.hpp" #include "../internal/is_attribute.hpp" #include "../parsing/NamedTupleParser.hpp" #include "../parsing/Parser.hpp" #include "Reader.hpp" #include "Writer.hpp" -namespace rfl { -namespace parsing { +namespace rfl::parsing { /// XML is very special. It doesn't have proper support for arrays, which means /// that we just need to ignore empty containers. Therefore, we need to a /// template specialization for the NamedTuple parser to accommodate for it. template -requires AreReaderAndWriter> + requires AreReaderAndWriter> struct Parser, ProcessorsType> : public NamedTupleParser { -}; + FieldTypes...> {}; + +/// The generic parser is also special, because we need to ignore empty +/// containers, which means that we need to try to read the value as an array or +/// object before trying to read it as a string. Therefore, we need to a +/// template specialization for the generic parser to accommodate for it. +template + requires AreReaderAndWriter +struct Parser { + using InputVarType = typename xml::Reader::InputVarType; + + static Result read(const xml::Reader& _r, + const InputVarType& _var) noexcept { + static_assert(always_false_v, + "XML does not support reading generic types."); + return error("XML does not support reading generic types."); + } -} // namespace parsing -} // namespace rfl + static void write(const xml::Writer& _w, const Generic& _generic, + const auto& _parent) { + Parser::write(_w, _generic.reflection(), _parent); + } + + static schema::Type to_schema( + std::map* _definitions) { + return Parser::to_schema(_definitions); + } +}; -namespace rfl { -namespace xml { +} // namespace rfl::parsing +namespace rfl::xml { template using Parser = parsing::Parser; -} -} // namespace rfl +} // namespace rfl::xml #endif diff --git a/include/rfl/xml/Reader.hpp b/include/rfl/xml/Reader.hpp index 67f2c98d..ee57ef13 100644 --- a/include/rfl/xml/Reader.hpp +++ b/include/rfl/xml/Reader.hpp @@ -9,12 +9,12 @@ #include #include +#include "../Generic.hpp" #include "../Result.hpp" #include "../always_false.hpp" #include "../parsing/is_view_reader.hpp" -namespace rfl { -namespace xml { +namespace rfl::xml { struct Reader { struct XMLInputArray { @@ -185,7 +185,6 @@ struct Reader { } }; -} // namespace xml -} // namespace rfl +} // namespace rfl::xml #endif diff --git a/tests/xml/test_generic.cpp b/tests/xml/test_generic.cpp index 9116f12f..eac439bb 100644 --- a/tests/xml/test_generic.cpp +++ b/tests/xml/test_generic.cpp @@ -14,11 +14,13 @@ TEST(xml, test_generic) { const auto xml_string = rfl::xml::write<"cat">(cat); - std::cout << xml_string << std::endl; - - const auto generic_cat = - rfl::xml::read>(xml_string); - - std::cout << rfl::xml::write<"cat">(generic_cat) << std::endl; + EXPECT_EQ(xml_string, + R"( + + Cachou + black + cat + +)"); } } // namespace test_generic From fb988769372649279be3e6ce978cc1ecf9d3aef8 Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sat, 7 Mar 2026 17:18:39 +0100 Subject: [PATCH 4/5] Document that reading into generics is not supported for XML --- docs/generic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generic.md b/docs/generic.md index 99005d1b..8fde288a 100644 --- a/docs/generic.md +++ b/docs/generic.md @@ -5,7 +5,7 @@ reflect-cpp is intended to be used to directly parse into structs. Doing this is But in some cases, we simply cannot anticipate the complete structure of the data at compile time. For these cases, we have `rfl::Generic`. -Note that generics are not supported for Avro. +Note that generics are not supported for Avro. For XML, generics are supported but only for writing, not for reading. `rfl::Generic` is a convenience wrapper around the following type: From 06192439e0a11a1bcb84757e62ff28c71874d5c3 Mon Sep 17 00:00:00 2001 From: "Dr. Patrick Urbanke" Date: Sat, 7 Mar 2026 17:32:05 +0100 Subject: [PATCH 5/5] Removed unused include --- include/rfl/xml/Reader.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/rfl/xml/Reader.hpp b/include/rfl/xml/Reader.hpp index ee57ef13..8f096c70 100644 --- a/include/rfl/xml/Reader.hpp +++ b/include/rfl/xml/Reader.hpp @@ -9,7 +9,6 @@ #include #include -#include "../Generic.hpp" #include "../Result.hpp" #include "../always_false.hpp" #include "../parsing/is_view_reader.hpp"