QXmpp  Version: 1.15.1
QXmppXmlTags_p.h
1 // SPDX-FileCopyrightText: 2025 Linus Jahn <lnj@kaidan.im>
2 //
3 // SPDX-License-Identifier: LGPL-2.1-or-later
4 
5 #ifndef QXMPPXMLTAGS_P_H
6 #define QXMPPXMLTAGS_P_H
7 
8 #include <tuple>
9 
10 #include <QStringView>
11 
12 namespace QXmpp::Private {
13 
14 template<typename Name, std::convertible_to<QStringView> Xmlns>
15 struct Tag {
16  Name name;
17  Xmlns xmlns;
18 
19  using NameType = Name;
20  using XmlnsType = Xmlns;
21 
22  Tag(Name name, Xmlns xmlns)
23  : name(std::forward<Name>(name)), xmlns(std::forward<Xmlns>(xmlns)) { }
24 
25  template<typename N, typename X>
26  Tag(std::tuple<N, X> &&t) : name(std::get<0>(t)), xmlns(std::get<1>(t)) { }
27  template<typename N, typename X>
28  Tag(const std::tuple<N, X> &t) : name(std::get<0>(t)), xmlns(std::get<1>(t)) { }
29 };
30 
31 template<size_t N, std::convertible_to<QStringView> Xmlns>
32 Tag(const char16_t (&str)[N], Xmlns &&) -> Tag<QStringView, Xmlns>;
33 
34 template<typename Name, std::convertible_to<QStringView> Xmlns>
35 Tag(Name &&, Xmlns &&) -> Tag<Name, Xmlns>;
36 
37 template<typename Name, typename Xmlns>
38 Tag(std::tuple<Name, Xmlns> &&) -> Tag<Name, Xmlns>;
39 
40 template<typename T>
41 concept IsXmlTag =
42  std::is_convertible_v<T, Tag<QStringView, QStringView>> || requires() {
43  typename T::NameType;
44  typename T::XmlnsType;
45  requires std::same_as<std::remove_cvref_t<T>, Tag<typename T::NameType, typename T::XmlnsType>>;
46  };
47 
48 template<typename T>
49 concept HasXmlTag =
50  !std::is_void_v<T> &&
51  requires { { T::XmlTag }; } &&
52  IsXmlTag<decltype(T::XmlTag)>;
53 
54 template<typename T>
55 concept HasPayloadXmlTagDirect =
56  requires { { T::PayloadXmlTag }; } &&
57  IsXmlTag<decltype(T::PayloadXmlTag)>;
58 
59 template<typename T>
60 concept HasPayloadXmlTagIndirect =
61  requires { typename T::PayloadType; } &&
62  IsXmlTag<decltype(T::PayloadType::XmlTag)>;
63 
64 template<typename T>
65 concept HasPayloadXmlTag = HasPayloadXmlTagDirect<T> || HasPayloadXmlTagIndirect<T>;
66 
67 template<HasPayloadXmlTag T>
68 constexpr auto PayloadXmlTag = [] {
69  if constexpr (HasPayloadXmlTagIndirect<T>) {
70  return T::PayloadType::XmlTag;
71  } else if constexpr (HasPayloadXmlTagDirect<T>) {
72  return T::PayloadXmlTag;
73  }
74 }();
75 
76 template<typename T>
77 concept HasCustomCheckIqType =
78  requires(const QString &s1, const QString &s2) {
79  { T::checkIqType(s1, s2) } -> std::convertible_to<bool>;
80  };
81 
82 template<typename T, IsXmlTag Tag>
83 bool isPayloadType(Tag xmlTag)
84 {
85  static_assert(
86  Private::HasPayloadXmlTag<T> || HasCustomCheckIqType<T>,
87  "T must offer PayloadXmlTag, PayloadType::XmlTag or checkIqType()");
88 
89  if constexpr (Private::HasPayloadXmlTag<T>) {
90  return xmlTag == Private::PayloadXmlTag<T>;
91  } else if constexpr (HasCustomCheckIqType<T>) {
92  static_assert(std::convertible_to<std::tuple_element_t<0, Tag>, QString>);
93  static_assert(std::convertible_to<std::tuple_element_t<1, Tag>, QString>);
94 
95  auto &[name, xmlns] = xmlTag;
96  return T::checkIqType(name, xmlns);
97  }
98 }
99 
100 } // namespace QXmpp::Private
101 
102 #endif // QXMPPXMLTAGS_P_H
Definition: QXmppTask.h:646
Definition: Algorithms.h:14