128 lines
5.5 KiB
C++
128 lines
5.5 KiB
C++
#pragma once
|
|
#include <libxml++/libxml++.h>
|
|
|
|
#include <larra/utils.hpp>
|
|
#include <nameof.hpp>
|
|
#include <ranges>
|
|
#include <variant>
|
|
|
|
namespace larra::xmpp {
|
|
|
|
namespace impl {
|
|
// std::isupper not declared as constexpr
|
|
constexpr auto IsUpper(char ch) -> bool {
|
|
return ch >= 'A' && ch <= 'Z';
|
|
}
|
|
|
|
constexpr auto ToLower(char ch) -> char {
|
|
return (ch >= 'A' && ch <= 'Z') ? static_cast<char>(ch + ('a' - 'A')) : ch;
|
|
}
|
|
|
|
template <typename T>
|
|
constexpr auto ToKebabCaseName() -> std::string_view {
|
|
static constexpr auto rawStr = nameof::nameof_short_type<T>();
|
|
|
|
constexpr auto str = [] {
|
|
return rawStr //
|
|
| std::views::transform([](auto ch) {
|
|
return impl::IsUpper(ch) ? std::array<char, 2>{'-', impl::ToLower(ch)} : std::array<char, 2>{ch, '\0'};
|
|
}) //
|
|
| std::views::join //
|
|
| std::views::filter([](char ch) {
|
|
return ch != '\0';
|
|
}) //
|
|
| std::views::drop(1);
|
|
};
|
|
static constexpr auto arr = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
|
|
return {arr.data(), arr.size()};
|
|
}
|
|
|
|
} // namespace impl
|
|
|
|
namespace error::stream {
|
|
|
|
struct BaseError : std::exception {};
|
|
|
|
// DO NOT MOVE TO ANOTHER NAMESPACE(where no heirs). VIA friend A FUNCTION IS ADDED THAT VIA ADL WILL BE SEARCHED FOR HEIRS
|
|
// C++20 modules very unstable in clangd :(
|
|
template <typename T>
|
|
struct ErrorImpl : BaseError {
|
|
static constexpr auto kDefaultName = "stream:error";
|
|
static inline const auto kKebabCaseName = static_cast<std::string>(impl::ToKebabCaseName<T>());
|
|
|
|
static constexpr auto kErrorMessage = [] -> std::string_view {
|
|
static constexpr auto name = nameof::nameof_short_type<T>();
|
|
static constexpr auto str = [] {
|
|
return std::array{std::string_view{"Stream Error: "}, std::string_view{name}, std::string_view{"\0", 1}} | std::views::join;
|
|
};
|
|
static constexpr auto array = str() | std::ranges::to<utils::RangeToWrapper<std::array<char, std::ranges::distance(str())>>>();
|
|
return {array.data(), array.size() - 1};
|
|
}();
|
|
static constexpr auto TryParse(xmlpp::Element* element) -> std::optional<T> {
|
|
return element ? element->get_first_child(kKebabCaseName) ? std::optional{T{}} : std::nullopt : std::nullopt;
|
|
}
|
|
static constexpr auto Parse(xmlpp::Element* element) -> T {
|
|
return TryParse(element).value();
|
|
}
|
|
friend constexpr auto operator<<(xmlpp::Element* element, const T& obj) -> void {
|
|
auto node = element->add_child_element(kKebabCaseName);
|
|
node->set_namespace_declaration("urn:ietf:params:xml:ns:xmpp-streams");
|
|
}
|
|
[[nodiscard]] constexpr auto what() const noexcept -> const char* override {
|
|
return kErrorMessage.data();
|
|
}
|
|
};
|
|
|
|
struct BadFormat : ErrorImpl<BadFormat> {};
|
|
struct BadNamespacePrefix : ErrorImpl<BadNamespacePrefix> {};
|
|
struct Conflict : ErrorImpl<Conflict> {};
|
|
struct ConnectionTimeout : ErrorImpl<ConnectionTimeout> {};
|
|
struct HostGone : ErrorImpl<HostGone> {};
|
|
struct HostUnknown : ErrorImpl<HostUnknown> {};
|
|
struct ImproperAdressing : ErrorImpl<ImproperAdressing> {};
|
|
struct InternalServerError : ErrorImpl<InternalServerError> {};
|
|
struct InvalidForm : ErrorImpl<InvalidForm> {};
|
|
struct InvalidNamespace : ErrorImpl<InvalidNamespace> {};
|
|
struct InvalidXml : ErrorImpl<InvalidXml> {};
|
|
struct NotAuthorized : ErrorImpl<NotAuthorized> {};
|
|
struct NotWellFormed : ErrorImpl<NotWellFormed> {};
|
|
struct PolicyViolation : ErrorImpl<PolicyViolation> {};
|
|
struct RemoteConnectionFailed : ErrorImpl<RemoteConnectionFailed> {};
|
|
struct Reset : ErrorImpl<Reset> {};
|
|
struct ResourceConstraint : ErrorImpl<ResourceConstraint> {};
|
|
struct RestrictedXml : ErrorImpl<RestrictedXml> {};
|
|
struct SeeOtherHost : ErrorImpl<SeeOtherHost> {};
|
|
struct SystemShutdown : ErrorImpl<SystemShutdown> {};
|
|
struct UndefinedCondition : ErrorImpl<UndefinedCondition> {};
|
|
struct UnsupportedEncoding : ErrorImpl<UnsupportedEncoding> {};
|
|
struct UnsupportedFeature : ErrorImpl<UnsupportedFeature> {};
|
|
struct UnsupportedStanzaType : ErrorImpl<UnsupportedStanzaType> {};
|
|
struct UnsupportedVersion : ErrorImpl<UnsupportedVersion> {};
|
|
|
|
} // namespace error::stream
|
|
|
|
using StreamError = std::variant<error::stream::BadFormat,
|
|
error::stream::BadNamespacePrefix,
|
|
error::stream::Conflict,
|
|
error::stream::ConnectionTimeout,
|
|
error::stream::HostGone,
|
|
error::stream::HostUnknown,
|
|
error::stream::ImproperAdressing,
|
|
error::stream::InternalServerError,
|
|
error::stream::InvalidForm,
|
|
error::stream::InvalidNamespace,
|
|
error::stream::InvalidXml,
|
|
error::stream::NotAuthorized,
|
|
error::stream::NotWellFormed,
|
|
error::stream::PolicyViolation,
|
|
error::stream::RemoteConnectionFailed,
|
|
error::stream::RestrictedXml,
|
|
error::stream::SeeOtherHost,
|
|
error::stream::SystemShutdown,
|
|
error::stream::UndefinedCondition,
|
|
error::stream::UnsupportedEncoding,
|
|
error::stream::UnsupportedFeature,
|
|
error::stream::UnsupportedStanzaType,
|
|
error::stream::UnsupportedVersion>;
|
|
|
|
} // namespace larra::xmpp
|