Add ConstructT option for boost pfr FieldSetHelper With
This commit is contained in:
parent
e7e84860cc
commit
eafdecba7b
8 changed files with 160 additions and 28 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -29,3 +29,4 @@ ext/
|
|||
libxmlplusplus-prefix/
|
||||
spdlog.pc
|
||||
build*
|
||||
larra
|
||||
|
|
74
library/include/larra/client/challenge_response.hpp
Normal file
74
library/include/larra/client/challenge_response.hpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
#include <libxml++/document.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace larra::xmpp::client::sasl {
|
||||
|
||||
struct Failure : std::exception {
|
||||
std::optional<std::string> text;
|
||||
constexpr Failure(std::optional<std::string> str) : text(std::move(str)) {};
|
||||
static constexpr auto kDefaultName = "failure";
|
||||
static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-sasl";
|
||||
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<Failure> {
|
||||
return std::optional{Failure{[&] -> std::optional<std::string> {
|
||||
auto textNode = element->get_first_child("text");
|
||||
if(!textNode) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto text = dynamic_cast<xmlpp::Element*>(textNode);
|
||||
if(!text) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto childText = text->get_first_child_text();
|
||||
if(!childText) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return childText->get_content();
|
||||
}()}};
|
||||
}
|
||||
static constexpr auto Parse(xmlpp::Element* element) -> Failure {
|
||||
return TryParse(element).value();
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Failure& failure) {
|
||||
}
|
||||
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
||||
return this->text ? this->text->c_str() : "Sasl failure";
|
||||
}
|
||||
};
|
||||
|
||||
struct Success {
|
||||
static constexpr auto kDefaultName = "success";
|
||||
static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-sasl";
|
||||
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<Success> {
|
||||
return std::optional{Success{}};
|
||||
}
|
||||
static constexpr auto Parse(xmlpp::Element* element) -> Success {
|
||||
return TryParse(element).value();
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Success& failure) {
|
||||
}
|
||||
};
|
||||
|
||||
struct Abort : std::exception {
|
||||
static constexpr auto kDefaultName = "abort";
|
||||
static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-sasl";
|
||||
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<Abort> {
|
||||
return element->get_first_child("aborted") ? std::optional{Abort{}} : std::nullopt;
|
||||
}
|
||||
static constexpr auto Parse(xmlpp::Element* element) -> Abort {
|
||||
return TryParse(element).value();
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Abort& failure) {
|
||||
element->set_namespace_declaration("urn:ietf:params:xml:ns:xmpp-sasl");
|
||||
}
|
||||
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
||||
return "Sasl Abort";
|
||||
}
|
||||
};
|
||||
|
||||
using Response = std::variant<Failure, Success, Abort>;
|
||||
|
||||
} // namespace larra::xmpp::client::sasl
|
40
library/include/larra/client/starttls_response.hpp
Normal file
40
library/include/larra/client/starttls_response.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
#include <libxml++/libxml++.h>
|
||||
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
namespace larra::xmpp::client::starttls {
|
||||
|
||||
struct Failure : std::exception {
|
||||
static constexpr auto kDefaultName = "failure";
|
||||
static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-sasl";
|
||||
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<Failure> {
|
||||
return element->get_name() == kDefaultName ? std::optional{Failure{}} : std::nullopt;
|
||||
}
|
||||
static constexpr auto Parse(xmlpp::Element* element) -> Failure {
|
||||
return TryParse(element).value();
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Failure& failure) {
|
||||
}
|
||||
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
||||
return "StartTLS Failure";
|
||||
}
|
||||
};
|
||||
|
||||
struct Success {
|
||||
static constexpr auto kDefaultName = "success";
|
||||
static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-tls";
|
||||
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<Success> {
|
||||
return element->get_name() == kDefaultName ? std::optional{Success{}} : std::nullopt;
|
||||
}
|
||||
static constexpr auto Parse(xmlpp::Element* element) -> Success {
|
||||
return TryParse(element).value();
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Success& failure) {
|
||||
}
|
||||
};
|
||||
|
||||
using Response = std::variant<Failure, Success>;
|
||||
|
||||
} // namespace larra::xmpp::client::starttls
|
|
@ -15,12 +15,12 @@ struct BareJid {
|
|||
|
||||
constexpr auto operator==(const BareJid&) const -> bool = default;
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Username(this Self&& self, std::string username) -> BareJid {
|
||||
[[nodiscard]] constexpr auto Username(this Self&& self, std::string username) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"username", BareJid>(std::forward<Self>(self), std::move(username));
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> BareJid {
|
||||
[[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"server", BareJid>(std::forward<Self>(self), std::move(server));
|
||||
}
|
||||
};
|
||||
|
@ -34,12 +34,12 @@ struct BareResourceJid {
|
|||
constexpr auto operator==(const BareResourceJid&) const -> bool = default;
|
||||
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> BareResourceJid {
|
||||
[[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"server", BareResourceJid>(std::forward<Self>(self), std::move(server));
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Resource(this Self&& self, std::string resource) -> BareResourceJid {
|
||||
[[nodiscard]] constexpr auto Resource(this Self&& self, std::string resource) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"resource", BareResourceJid>(std::forward<Self>(self), std::move(resource));
|
||||
}
|
||||
};
|
||||
|
@ -54,17 +54,17 @@ struct FullJid {
|
|||
constexpr auto operator==(const FullJid&) const -> bool = default;
|
||||
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Username(this Self&& self, std::string username) -> FullJid {
|
||||
[[nodiscard]] constexpr auto Username(this Self&& self, std::string username) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"username", FullJid>(std::forward<Self>(self), std::move(username));
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> FullJid {
|
||||
[[nodiscard]] constexpr auto Server(this Self&& self, std::string server) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"server", FullJid>(std::forward<Self>(self), std::move(server));
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Resource(this Self&& self, std::string resource) -> FullJid {
|
||||
[[nodiscard]] constexpr auto Resource(this Self&& self, std::string resource) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"resource", FullJid>(std::forward<Self>(self), std::move(resource));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -48,11 +48,11 @@ struct Initial {
|
|||
FullJid from;
|
||||
BareJid to;
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto From(this Self&& self, BareJid value) -> Initial {
|
||||
[[nodiscard]] constexpr auto From(this Self&& self, BareJid value) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"from", Initial>(std::forward<Self>(self), std::move(value));
|
||||
}
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto To(this Self&& self, BareJid value) -> Initial {
|
||||
[[nodiscard]] constexpr auto To(this Self&& self, BareJid value) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"to", Initial>(std::forward<Self>(self), std::move(value));
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Initial& presence) {
|
||||
|
@ -78,15 +78,15 @@ struct Probe {
|
|||
BareJid to;
|
||||
std::string id;
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto From(this Self&& self, BareJid value) -> Probe {
|
||||
[[nodiscard]] constexpr auto From(this Self&& self, BareJid value) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"from", Probe>(std::forward<Self>(self), std::move(value));
|
||||
}
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto To(this Self&& self, BareJid value) -> Probe {
|
||||
[[nodiscard]] constexpr auto To(this Self&& self, BareJid value) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"to", Probe>(std::forward<Self>(self), std::move(value));
|
||||
}
|
||||
template <typename Self>
|
||||
[[nodiscard]] constexpr auto Id(this Self&& self, std::string value) -> Probe {
|
||||
[[nodiscard]] constexpr auto Id(this Self&& self, std::string value) -> std::decay_t<Self> {
|
||||
return utils::FieldSetHelper::With<"id", Probe>(std::forward<Self>(self), std::move(value));
|
||||
}
|
||||
friend constexpr auto operator<<(xmlpp::Element* element, const Probe& presence) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include <boost/pfr.hpp>
|
||||
#include <ranges>
|
||||
#include <utempl/utils.hpp>
|
||||
|
||||
namespace larra::xmpp::utils {
|
||||
|
@ -8,7 +7,7 @@ namespace larra::xmpp::utils {
|
|||
namespace impl {
|
||||
|
||||
template <typename T, typename R>
|
||||
constexpr auto GetType(R(T::*ptr)) -> R;
|
||||
constexpr auto GetType(R(T::* ptr)) -> R;
|
||||
|
||||
template <typename T>
|
||||
using GetTypeT = decltype(GetType(std::declval<T>()));
|
||||
|
@ -54,7 +53,7 @@ struct FieldsDescription {
|
|||
* \return an object of type std::decay_t<Self> with data from T with fields from \ref self and the \ref value of the field with index
|
||||
* \ref I
|
||||
*/
|
||||
template <std::size_t I, typename Self, typename Value>
|
||||
template <std::size_t I, typename Self, typename Value> // NOLINTNEXTLINE
|
||||
constexpr auto With(Self&& self, Value&& value) const -> std::decay_t<Self>
|
||||
requires(std::constructible_from<std::decay_t<Self>, T> && std::is_constructible_v<T, impl::GetTypeT<Fs>...> &&
|
||||
impl::SetConcept<Self, std::decay_t<Value>, Fs...> &&
|
||||
|
@ -84,9 +83,9 @@ struct FieldsDescription {
|
|||
* \param value new value for field
|
||||
* \return an object of type std::decay_t<Self> with data from T with fields from \ref self and the \ref value of the field \ref ptr
|
||||
*/
|
||||
template <typename Self, typename Value, typename Type>
|
||||
constexpr auto With(Type(T::*ptr), Self&& self, Value&& value) const
|
||||
requires(std::is_constructible_v<T, impl::GetTypeT<Fs>...> && std::is_constructible_v<std::decay_t<Self>, T> &&
|
||||
template <typename Self, typename Value, typename Type> // NOLINTNEXTLINE
|
||||
constexpr auto With(Type(T::* ptr), Self&& self, Value&& value) const -> std::decay_t<Self>
|
||||
requires(std::is_constructible_v<T, impl::GetTypeT<Fs>...> && std::constructible_from<std::decay_t<Self>, T> &&
|
||||
std::is_constructible_v<Type, decltype(value)> && impl::SetConcept<Self, Type, Fs...>)
|
||||
{
|
||||
return std::decay_t<Self>{utempl::Unpack(this->tuple, [&](auto... fs) -> T {
|
||||
|
@ -165,14 +164,17 @@ struct FieldSetHelper {
|
|||
*/
|
||||
template <std::size_t I,
|
||||
typename T = void,
|
||||
bool ConstructT = true,
|
||||
typename Self,
|
||||
typename Value,
|
||||
typename...,
|
||||
typename Type = std::conditional_t<std::same_as<T, void>, std::decay_t<Self>, T>,
|
||||
typename TT = decltype(impl::GCCWorkaround<T, Self>())>
|
||||
static constexpr auto With(Self&& self, Value&& value) -> std::decay_t<Self>
|
||||
requires(std::constructible_from<std::decay_t<Self>, Type> && std::is_aggregate_v<Type> &&
|
||||
(std::same_as<T, void> || requires { static_cast<const T&>(self); }) && I < boost::pfr::tuple_size_v<Type> &&
|
||||
typename TT = decltype(impl::GCCWorkaround<T, Self>())> // NOLINTNEXTLINE
|
||||
static constexpr auto With(Self&& self, Value&& value) -> std::conditional_t<ConstructT, std::decay_t<Self>, Type>
|
||||
requires(std::is_aggregate_v<Type> &&
|
||||
(!ConstructT || (std::constructible_from<std::decay_t<Self>, Type> &&
|
||||
(std::same_as<T, void> || requires { static_cast<const T&>(self); }))) &&
|
||||
I < boost::pfr::tuple_size_v<Type> &&
|
||||
std::is_constructible_v<std::decay_t<decltype(boost::pfr::get<I>(std::declval<TT>()))>, decltype(value)> &&
|
||||
[](auto... is) {
|
||||
return ((*is == I ? true
|
||||
|
@ -182,12 +184,12 @@ struct FieldSetHelper {
|
|||
std::is_constructible_v<Type, decltype(boost::pfr::get<*is>(std::declval<TT>()))...>;
|
||||
} | utempl::kSeq<boost::pfr::tuple_size_v<Type>>)
|
||||
{
|
||||
return std::decay_t<Self>{[&](auto... is) -> Type {
|
||||
return std::conditional_t<ConstructT, std::decay_t<Self>, Type>{[&](auto... is) -> Type {
|
||||
return {[&] -> decltype(auto) {
|
||||
if constexpr(I == *is) {
|
||||
return std::forward<Value>(value);
|
||||
} else {
|
||||
return std::forward_like<Self>(boost::pfr::get<*is>(static_cast<TT&>(self)));
|
||||
return std::forward_like<Self>(boost::pfr::get<*is>(static_cast<std::conditional_t<ConstructT, TT&, decltype(self)>>(self)));
|
||||
}
|
||||
}()...};
|
||||
} | utempl::kSeq<boost::pfr::tuple_size_v<TT>>};
|
||||
|
@ -203,15 +205,15 @@ struct FieldSetHelper {
|
|||
* \returns an object of type std::decay_t<Self> with data from Type constructed with fields with \ref self and the \ref value of the field named \ref FieldName where Type is
|
||||
* std::conditional_t<std::same_as<\ref T, void>, std::decay_t<Self>, \ref T>
|
||||
*/
|
||||
template <utempl::ConstexprString FieldName, typename T = void, typename Self, typename Value>
|
||||
template <utempl::ConstexprString FieldName, typename T = void, bool ConstructT = true, typename Self, typename Value>
|
||||
static constexpr auto With(Self&& self, Value&& value) -> decltype(With<[] {
|
||||
constexpr auto names = boost::pfr::names_as_array<std::conditional_t<std::same_as<T, void>, std::decay_t<Self>, T>>();
|
||||
return std::ranges::find(names, static_cast<std::string_view>(FieldName)) - names.begin();
|
||||
}(),
|
||||
T>(std::forward<Self>(self), std::forward<Value>(value))) {
|
||||
T, ConstructT>(std::forward<Self>(self), std::forward<Value>(value))) {
|
||||
constexpr auto names = boost::pfr::names_as_array<std::conditional_t<std::same_as<T, void>, std::decay_t<Self>, T>>();
|
||||
constexpr auto id = std::ranges::find(names, static_cast<std::string_view>(FieldName)) - names.begin();
|
||||
return With<id, T>(std::forward<Self>(self), std::forward<Value>(value));
|
||||
return With<id, T, ConstructT>(std::forward<Self>(self), std::forward<Value>(value));
|
||||
};
|
||||
// clang-format on
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <larra/features.hpp>
|
||||
#include <ranges>
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ struct SomeStruct6 {
|
|||
};
|
||||
|
||||
struct SomeStruct7 : SomeStruct6 {
|
||||
SomeStruct7(SomeStruct6&& obj) : SomeStruct6(std::move(obj)) {};
|
||||
explicit SomeStruct7(SomeStruct6&& obj) : SomeStruct6(std::move(obj)) {};
|
||||
using SomeStruct6::SomeStruct6;
|
||||
};
|
||||
|
||||
|
@ -108,4 +108,18 @@ TEST(Set, Inheritance) {
|
|||
ASSERT_EQ(obj.field2, "World");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct SomeStruct8 {
|
||||
T value;
|
||||
template <typename TT, typename Self>
|
||||
constexpr auto Value(this Self&& self, TT value) {
|
||||
return utils::FieldSetHelper::With<0, SomeStruct8<TT>, false>(std::forward<Self>(self), std::move(value));
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Set, OtherType) {
|
||||
constexpr auto value = SomeStruct8{.value = 42}.Value<std::string_view>("Hello World");
|
||||
EXPECT_EQ(value.value, std::string_view{"Hello World"});
|
||||
}
|
||||
|
||||
} // namespace larra::xmpp
|
||||
|
|
Loading…
Reference in a new issue