10#include "QXmppStanza.h"
11#include "QXmppVisitHelper_p.h"
19namespace QXmpp::Private {
29struct Enums::Data<IqType> {
31 static constexpr auto Values = makeValues<IqType>({
34 { Result, u
"result" },
39template<IqType,
typename Payload =
void>
42template<
typename Payload =
void>
43using GetIq = Iq<IqType::Get, Payload>;
45template<
typename Payload =
void>
46using SetIq = Iq<IqType::Set, Payload>;
48template<
typename Payload =
void>
49using ResultIq = Iq<IqType::Result, Payload>;
51template<
typename Payload =
void>
52using ErrorIq = Iq<IqType::Error, Payload>;
54template<IqType Type,
typename Payload =
void>
55auto iqFromDomImpl(
const QDomElement &el) -> std::optional<Iq<Type, Payload>>;
57template<IqType Type,
typename Payload>
58 requires((Type == IqType::Get || Type == IqType::Set) && !std::is_void_v<Payload>)
59struct Iq<Type, Payload> {
66 using PayloadType = Payload;
67 static constexpr auto IqType = Type;
69 static std::optional<Iq> fromDom(
const QDomElement &el) {
return iqFromDomImpl<Type, Payload>(el); }
70 void toXml(XmlWriter &w)
const
74 Attribute { u
"id",
id },
75 OptionalAttribute { u
"from", from },
76 OptionalAttribute { u
"to", to },
77 Attribute { u
"type", Type },
78 OptionalAttribute { u
"xml:lang", lang },
84template<
typename Payload>
85struct Iq<IqType::Result, Payload> {
90 std::conditional_t<std::is_void_v<Payload>, std::monostate, Payload> payload;
92 using PayloadType = Payload;
94 static std::optional<Iq> fromDom(
const QDomElement &el) {
return iqFromDomImpl<IqType::Result, Payload>(el); }
95 void toXml(XmlWriter &w)
const
99 Attribute { u
"id",
id },
100 OptionalAttribute { u
"from", from },
101 OptionalAttribute { u
"to", to },
102 Attribute { u
"type", IqType::Result },
103 OptionalAttribute { u
"xml:lang", lang },
109template<
typename Payload>
110struct Iq<IqType::Error, Payload> {
115 std::conditional_t<std::is_void_v<Payload>, std::monostate, std::optional<Payload>> payload;
118 using PayloadType = Payload;
120 static std::optional<Iq> fromDom(
const QDomElement &el) {
return iqFromDomImpl<IqType::Error, Payload>(el); }
121 void toXml(XmlWriter &w)
const
125 Attribute { u
"id",
id },
126 OptionalAttribute { u
"from", from },
127 OptionalAttribute { u
"to", to },
128 Attribute { u
"type", IqType::Error },
129 OptionalAttribute { u
"xml:lang", lang },
136template<IqType Type,
typename Payload>
137auto iqFromDomImpl(
const QDomElement &el) -> std::optional<Iq<Type, Payload>>
139 using IqT = Iq<Type, Payload>;
141 if (el.tagName() == u
"iq" && el.hasAttribute(u
"id"_s) && el.attribute(u
"type"_s) == Type) {
142 auto id = el.attribute(u
"id"_s);
143 auto from = el.attribute(u
"from"_s);
144 auto to = el.attribute(u
"to"_s);
145 auto lang = el.attributeNS(ns_xml.toString(), u
"lang"_s);
147 if constexpr (Type == IqType::Get || Type == IqType::Set) {
148 if (
auto payload = parseOptionalElement<Payload>(el.firstChildElement())) {
157 }
else if constexpr (Type == IqType::Result) {
158 if constexpr (std::is_void_v<Payload>) {
159 return IqT { std::move(
id), std::move(from), std::move(to), std::move(lang) };
161 if (
auto payload = parseOptionalElement<Payload>(el.firstChildElement())) {
171 }
else if constexpr (Type == IqType::Error) {
172 auto errorEl = el.lastChildElement();
173 auto payloadEl = errorEl.previousSiblingElement();
175 if (
auto error = parseOptionalElement<QXmppStanza::Error>(errorEl)) {
181 parseOptionalElement<Payload>(payloadEl),
191template<
typename Payload>
192auto parseIqResponse(std::variant<QDomElement, QXmppError> &&sendResult) -> std::variant<Payload, QXmppError>
195 using Result = std::variant<Payload, QXmppError>;
198 [](QDomElement &&el) -> Result {
199 auto type = el.attribute(u
"type"_s);
200 if (type == IqType::Result) {
201 if (
auto payload = parseElement<Payload>(el.firstChildElement())) {
202 return std::move(*payload);
205 u
"Failed to parse IQ result payload"_s,
206 StanzaError(StanzaError::Cancel, StanzaError::UndefinedCondition),
209 }
else if (type == IqType::Error) {
210 if (
auto error = parseElement<StanzaError>(el.lastChildElement())) {
214 u
"Failed to parse error response"_s,
220 u
"Received unexpected IQ type"_s,
225 std::move(sendResult));
229template<
typename Payload>
233 std::optional<Payload> payload;
235 template<IqType Type>
236 requires(Type == IqType::Get || Type == IqType::Set)
237 CompatIq(Iq<Type, Payload> &&iq) :
QXmppIq(), payload(std::move(iq.payload))
259 void parseElementFromChild(
const QDomElement &el)
override
261 payload = parseElement<Payload>(el.firstChildElement());
263 void toXmlElementFromChild(QXmlStreamWriter *writer)
const override
265 XmlWriter(writer).write(payload);
The QXmppIq class is the base class for all IQs.
Definition QXmppIq.h:23
@ Set
Set request.
Definition QXmppIq.h:29
@ Get
Get request.
Definition QXmppIq.h:28
@ Result
Result.
Definition QXmppIq.h:30
void setType(QXmppIq::Type)
Definition QXmppIq.cpp:70
The Error class represents a stanza error.
Definition QXmppStanza.h:96
QString text() const
Definition QXmppStanza.cpp:219
@ Modify
The request needs to be changed and resent.
Definition QXmppStanza.h:106
@ Cancel
The error is not temporary.
Definition QXmppStanza.h:104
@ UndefinedCondition
An undefined condition was hit.
Definition QXmppStanza.h:138
@ UnexpectedRequest
The request was unexpected.
Definition QXmppStanza.h:139
void setLang(const QString &)
Definition QXmppStanza.cpp:739
void setFrom(const QString &)
Definition QXmppStanza.cpp:703
void setTo(const QString &)
Definition QXmppStanza.cpp:685
void setId(const QString &)
Definition QXmppStanza.cpp:721
Definition QXmppError.h:17