Skip to content

Commit 03cbb92

Browse files
committed
xml: raw nodes
1 parent 4614d85 commit 03cbb92

4 files changed

Lines changed: 41 additions & 10 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#pragma once
2+
3+
namespace rsl::annotations::inline serializer {
4+
struct Skip {};
5+
constexpr inline Skip skip{};
6+
}; // namespace rsl::annotations::inline serializer

include/rsl/serializer/machinery.hpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#pragma once
22
#include <meta>
33
#include <ranges>
4+
#include <rsl/meta_traits>
45
#include "util.hpp"
6+
#include "annotations.hpp"
57

68
namespace rsl::serializer {
79

@@ -64,13 +66,16 @@ struct Meta<T> {
6466
void descend(F&& visitor, U&& value) {
6567
template for (constexpr auto Idx : std::views::iota(0ZU, members.size())) {
6668
constexpr auto M = members[Idx];
67-
Member<Idx, M, typename[:type_of(M):]>{}.visit(visitor, value.[:M:]);
69+
if constexpr (!meta::has_annotation(M, ^^annotations::Skip)){
70+
Member<Idx, M, typename[:type_of(M):]>{}.visit(visitor, value.[:M:]);
71+
}
6872
}
6973
}
7074
};
7175

7276
template <std::ranges::range T>
73-
requires std::constructible_from<std::initializer_list<typename T::value_type>>
77+
requires(std::constructible_from<std::initializer_list<typename T::value_type>> &&
78+
!std::convertible_to<T, std::string_view>)
7479
struct Meta<T> {
7580
using type = T;
7681
using element_type = typename T::value_type;
@@ -111,4 +116,16 @@ struct Meta<std::optional<T>> {
111116
}
112117
};
113118

119+
template <std::convertible_to<std::string> T>
120+
struct Meta<T> {
121+
using type = T;
122+
constexpr static std::meta::info info = ^^T;
123+
124+
template <typename S, typename F, typename U>
125+
requires(std::same_as<std::remove_cvref_t<U>, type>)
126+
void visit(this S&& self, F&& visitor, U&& value) {
127+
std::invoke(std::forward<F>(visitor), std::forward<S>(self), std::forward<U>(value));
128+
}
129+
};
130+
114131
} // namespace rsl::serializer

include/rsl/serializer/xml/annotations.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace rsl::xml {
44
namespace annotations {
55
struct Attribute {};
6+
struct Raw {};
67
} // namespace annotations
78
constexpr inline annotations::Attribute attribute{};
9+
constexpr inline annotations::Raw raw{};
810
} // namespace rsl::xml

include/rsl/serializer/xml/serializer.hpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include "document.hpp"
33
#include "rsl/serializer/xml/annotations.hpp"
44

5+
#include <format>
6+
57
#include <rsl/meta_traits>
68
#include <rsl/serializer/machinery.hpp>
79
#include <stdexcept>
@@ -27,7 +29,8 @@ class Serializer {
2729
}
2830

2931
[[nodiscard]] std::string get_header() const {
30-
return R"(<?xml version="1.0" encoding="UTF-8"?>)""\n";
32+
return R"(<?xml version="1.0" encoding="UTF-8"?>)"
33+
"\n";
3134
}
3235

3336
public:
@@ -72,25 +75,28 @@ class Serializer {
7275
throw std::runtime_error("Root node must be a structure");
7376
}
7477

75-
if constexpr (!meta::has_annotation(meta.info, ^^xml::annotations::Attribute)) {
76-
throw std::runtime_error("Non-structural fields can only be attributes.");
77-
} else {
78+
if constexpr (meta::has_annotation(meta.info, ^^xml::annotations::Attribute)) {
7879
if constexpr (!has_identifier(meta.info)) {
7980
throw std::runtime_error("Attributes must have identifiers.");
8081
} else {
8182
if constexpr (is_optional<R>) {
8283
if (value.has_value()) {
8384
cursor->attributes[std::string(identifier_of(meta.info))] = stringify_value(*value);
8485
}
85-
}else {
86+
} else {
8687
cursor->attributes[std::string(identifier_of(meta.info))] = stringify_value(value);
8788
}
8889
}
90+
} else if constexpr (meta::has_annotation(meta.info, ^^xml::annotations::Raw)){
91+
cursor = cursor->add({std::string(identifier_of(meta.info))});
92+
cursor->raw_content = stringify_value(value);
93+
cursor = cursor->parent;
94+
} else {
95+
throw std::runtime_error(std::format("Non-structural fields can only be attributes. {}",
96+
define_static_string(display_string_of(meta.info))));
8997
}
9098
}
9199

92-
[[nodiscard]] std::string finalize() const {
93-
return get_header() + document.stringify();
94-
}
100+
[[nodiscard]] std::string finalize() const { return get_header() + document.stringify(); }
95101
};
96102
} // namespace rsl::serializer::_xml_impl

0 commit comments

Comments
 (0)