This commit is contained in:
sha512sum 2024-10-19 18:15:24 +00:00
parent ed4276338d
commit ae1f5c2d24
2 changed files with 45 additions and 7 deletions

View file

@ -68,10 +68,23 @@ struct Config<std::string> {
}; };
namespace impl { namespace impl {
template <typename T>
concept HasParse = requires(xmlpp::Element* e) {
{ T::Parse(e) } -> std::same_as<T>;
};
template <typename T, typename V> template <typename T, typename V>
struct Config : V { struct Config : V {
using V::V; using V::V;
constexpr Config()
requires HasParse<T>
: V(::larra::xmpp::serialization::Config<T>{}) {
}
constexpr Config()
requires(!HasParse<T>)
: V(AttributeConfig{}) {
}
constexpr auto Base() const -> const V& { constexpr auto Base() const -> const V& {
return static_cast<const V&>(*this); return static_cast<const V&>(*this);
} }
@ -116,14 +129,18 @@ consteval auto FindElement(std::string_view field, utempl::TypeList<T> = {}) {
} }
template <auto& Config, typename Info> template <auto& Config, typename Info>
auto ParseField(xmlpp::Element* main) { auto ParseField(xmlpp::Element* main) -> std::decay_t<decltype(Config)>::type {
using Type = std::decay_t<decltype(Config)>::type; using Type = std::decay_t<decltype(Config)>::type;
if constexpr(std::holds_alternative<AttributeConfig>(Config.Base())) { if constexpr(std::holds_alternative<AttributeConfig>(Config.Base())) {
xmlpp::Attribute* node = main->get_attribute(Info::kName); xmlpp::Attribute* node = main->get_attribute(Info::kName);
if(!node) { if(!node) {
throw AttributeSerializationError(std::format("Attribute [{}] serialization error", Info::kName)); throw AttributeSerializationError(std::format("Attribute [{}] serialization error", Info::kName));
} }
return node->get_value(); if constexpr(requires(std::string_view view) { Type::Parse(view); }) {
return Type::Parse(node->get_value());
} else {
return node->get_value();
}
} else { } else {
return ElementSerializer<Type, Config, Info>::Parse(main); return ElementSerializer<Type, Config, Info>::Parse(main);
} }

View file

@ -1,5 +1,6 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <larra/jid.hpp>
#include <larra/serialization.hpp> #include <larra/serialization.hpp>
#include <larra/serialization/auto.hpp> #include <larra/serialization/auto.hpp>
#include <larra/serialization/error.hpp> #include <larra/serialization/error.hpp>
@ -55,6 +56,12 @@ struct SomeStruct4 {
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct4; [[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct4;
}; };
struct SomeStruct5 {
static constexpr auto kDefaultName = "some5";
BareJid value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct5;
};
} // namespace tests::serialization } // namespace tests::serialization
namespace serialization { namespace serialization {
@ -63,12 +70,13 @@ template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct> = SerializationConfig<tests::serialization::SomeStruct>{}; constexpr auto kSerializationConfig<tests::serialization::SomeStruct> = SerializationConfig<tests::serialization::SomeStruct>{};
template <> template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct2> = constexpr auto kSerializationConfig<tests::serialization::SomeStruct2> = SerializationConfig<tests::serialization::SomeStruct2>{};
SerializationConfig<tests::serialization::SomeStruct2>{}.With<"value">(serialization::Config<tests::serialization::SomeStruct>{});
template <> template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct4> = constexpr auto kSerializationConfig<tests::serialization::SomeStruct4> = SerializationConfig<tests::serialization::SomeStruct4>{};
SerializationConfig<tests::serialization::SomeStruct4>{}.With<"value">(serialization::Config<tests::serialization::SomeStruct3>{});
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct5> = SerializationConfig<tests::serialization::SomeStruct5>{};
} // namespace serialization } // namespace serialization
@ -88,7 +96,11 @@ auto tests::serialization::SomeStruct4::Parse(xmlpp::Element* element) -> SomeSt
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct4>(element); return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct4>(element);
} }
TEST(Parse, Auto) { auto tests::serialization::SomeStruct5::Parse(xmlpp::Element* element) -> SomeStruct5 {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct5>(element);
}
TEST(AutoParse, Basic) {
xmlpp::Document doc; xmlpp::Document doc;
auto node = doc.create_root_node("some2"); auto node = doc.create_root_node("some2");
node = node->add_child_element("some"); node = node->add_child_element("some");
@ -104,4 +116,13 @@ TEST(Parse, Auto) {
EXPECT_EQ(c.value.value, 42); EXPECT_EQ(c.value.value, 42);
} }
TEST(AutoParse, Attribute) {
xmlpp::Document doc;
auto node = doc.create_root_node("some5");
node->set_attribute("value", "user@server.i2p");
auto a = Serialization<tests::serialization::SomeStruct5>::Parse(node);
EXPECT_EQ(a.value.server, "server.i2p"sv);
EXPECT_EQ(a.value.username, "user"sv);
}
} // namespace larra::xmpp } // namespace larra::xmpp