Loading...
Searching...
No Matches
QXmppXmlTags_p.h
// SPDX-FileCopyrightText: 2025 Linus Jahn <lnj@kaidan.im>
//
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifndef QXMPPXMLTAGS_P_H
#define QXMPPXMLTAGS_P_H
#include <tuple>
#include <QStringView>
namespace QXmpp::Private {
template<typename Name, std::convertible_to<QStringView> Xmlns>
struct Tag {
Name name;
Xmlns xmlns;
using NameType = Name;
using XmlnsType = Xmlns;
Tag(Name name, Xmlns xmlns)
: name(std::forward<Name>(name)), xmlns(std::forward<Xmlns>(xmlns)) { }
template<typename N, typename X>
Tag(std::tuple<N, X> &&t) : name(std::get<0>(t)), xmlns(std::get<1>(t)) { }
template<typename N, typename X>
Tag(const std::tuple<N, X> &t) : name(std::get<0>(t)), xmlns(std::get<1>(t)) { }
};
template<size_t N, std::convertible_to<QStringView> Xmlns>
Tag(const char16_t (&str)[N], Xmlns &&) -> Tag<QStringView, Xmlns>;
template<typename Name, std::convertible_to<QStringView> Xmlns>
Tag(Name &&, Xmlns &&) -> Tag<Name, Xmlns>;
template<typename Name, typename Xmlns>
Tag(std::tuple<Name, Xmlns> &&) -> Tag<Name, Xmlns>;
template<typename T>
concept IsXmlTag =
std::is_convertible_v<T, Tag<QStringView, QStringView>> || requires() {
typename T::NameType;
typename T::XmlnsType;
requires std::same_as<std::remove_cvref_t<T>, Tag<typename T::NameType, typename T::XmlnsType>>;
};
template<typename T>
concept HasXmlTag =
!std::is_void_v<T> &&
requires { { T::XmlTag }; } &&
IsXmlTag<decltype(T::XmlTag)>;
template<typename T>
concept HasPayloadXmlTagDirect =
requires { { T::PayloadXmlTag }; } &&
IsXmlTag<decltype(T::PayloadXmlTag)>;
template<typename T>
concept HasPayloadXmlTagIndirect =
requires { typename T::PayloadType; } &&
IsXmlTag<decltype(T::PayloadType::XmlTag)>;
template<typename T>
concept HasPayloadXmlTag = HasPayloadXmlTagDirect<T> || HasPayloadXmlTagIndirect<T>;
template<HasPayloadXmlTag T>
constexpr auto PayloadXmlTag = [] {
if constexpr (HasPayloadXmlTagIndirect<T>) {
return T::PayloadType::XmlTag;
} else if constexpr (HasPayloadXmlTagDirect<T>) {
return T::PayloadXmlTag;
}
}();
template<typename T>
concept HasCustomCheckIqType =
requires(const QString &s1, const QString &s2) {
{ T::checkIqType(s1, s2) } -> std::convertible_to<bool>;
};
template<typename T, IsXmlTag Tag>
bool isPayloadType(Tag xmlTag)
{
static_assert(
Private::HasPayloadXmlTag<T> || HasCustomCheckIqType<T>,
"T must offer PayloadXmlTag, PayloadType::XmlTag or checkIqType()");
if constexpr (Private::HasPayloadXmlTag<T>) {
return xmlTag == Private::PayloadXmlTag<T>;
} else if constexpr (HasCustomCheckIqType<T>) {
static_assert(std::convertible_to<std::tuple_element_t<0, Tag>, QString>);
static_assert(std::convertible_to<std::tuple_element_t<1, Tag>, QString>);
auto &[name, xmlns] = xmlTag;
return T::checkIqType(name, xmlns);
}
}
} // namespace QXmpp::Private
#endif // QXMPPXMLTAGS_P_H