From 46801080846d58ab1528e921bebcb14e651f7956 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 9 Jun 2018 22:53:29 +0900 Subject: csapi: Now really fix passing query parameters Also: GetContentThumbnailJob (again) requires width and height. --- lib/converters.h | 125 +++++++++++++++++++++++++++---------------------------- 1 file changed, 61 insertions(+), 64 deletions(-) (limited to 'lib/converters.h') diff --git a/lib/converters.h b/lib/converters.h index 711d0a7c..7de33c9b 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -82,22 +82,20 @@ namespace QMatrixClient T& value() { return _value; } T&& release() { _omitted = true; return std::move(_value); } - operator bool() const { return !_omitted; } + operator bool() const { return !omitted(); } private: T _value; bool _omitted; }; - // This catches anything implicitly convertible to QJsonValue/Object/Array inline auto toJson(const QJsonValue& val) { return val; } inline auto toJson(const QJsonObject& o) { return o; } inline auto toJson(const QJsonArray& arr) { return arr; } // Special-case QStrings and bools to avoid ambiguity between QJsonValue - // and QVariant (also, QString.isEmpty() is used in _impl::AddNote<> below) + // and QVariant (also, QString.isEmpty() is used in _impl::AddNode<> below) inline auto toJson(const QString& s) { return s; } - inline QJsonValue toJson(bool b) { return b; } inline QJsonArray toJson(const QStringList& strings) { @@ -109,7 +107,18 @@ namespace QMatrixClient return bytes.constData(); } - QJsonValue toJson(const QVariant& v); + // QVariant is outrageously omnivorous - it consumes whatever is not + // exactly matching the signature of other toJson overloads. The trick + // below disables implicit conversion to QVariant through its numerous + // non-explicit constructors. + QJsonValue variantToJson(const QVariant& v); + template + inline auto toJson(T&& var) + -> std::enable_if_t, QVariant>::value, + QJsonValue> + { + return variantToJson(var); + } QJsonObject toJson(const QMap& map); #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) QJsonObject toJson(const QHash& hMap); @@ -151,16 +160,6 @@ namespace QMatrixClient return json; } - template - inline auto toJson(const Omittable& omittable) - -> decltype(toJson(omittable.value())) - { - if (omittable) - return toJson(omittable.value()); - - return {}; - } - #if 0 template inline auto toJson(const optional& optVal) @@ -333,74 +332,72 @@ namespace QMatrixClient namespace _impl { + template + inline void addTo(QJsonObject& o, const QString& k, ValT&& v) + { o.insert(k, toJson(v)); } + + template + inline void addTo(QUrlQuery& q, const QString& k, ValT&& v) + { q.addQueryItem(k, QString("%1").arg(v)); } + + // OpenAPI is entirely JSON-based, which means representing bools as + // textual true/false, rather than 1/0. + template + inline void addTo(QUrlQuery& q, const QString& k, bool v) + { + q.addQueryItem(k, v ? QStringLiteral("true") + : QStringLiteral("false")); + } + // This one is for types that don't have isEmpty() - template + template struct AddNode { - static void impl(InserterT inserter, QString key, JsonT&& value) + template + static void impl(ContT& container, const QString& key, + ForwardedT&& value) { - inserter(std::move(key), std::forward(value)); + addTo(container, key, std::forward(value)); } }; // This one is for types that have isEmpty() - template - struct AddNode().isEmpty())> + template + struct AddNode().isEmpty())> { - static void impl(InserterT inserter, QString key, JsonT&& value) + template + static void impl(ContT& container, const QString& key, + ForwardedT&& value) { if (!value.isEmpty()) - inserter(std::move(key), std::forward(value)); + AddNode::impl(container, + key, std::forward(value)); } }; - template - inline void maybeAdd(InserterT inserter, QString key, ValT&& value) + // This is a special one that unfolds Omittable<> + template + struct AddNode, Force> { - auto&& json = toJson(std::forward(value)); - // QJsonValue doesn't have isEmpty and consumes all other types - // (QString, QJsonObject etc.). - AddNode> - ::impl(inserter, std::move(key), std::move(json)); - - } - + template + static void impl(ContT& container, + const QString& key, const OmittableT& value) + { + if (!value.omitted()) + AddNode::impl(container, key, value.value()); + else if (Force) // Edge case, no value but must put something + AddNode::impl(container, key, QString{}); + } + }; } // namespace _impl static constexpr bool IfNotEmpty = false; - template - inline void addToJson(QJsonObject& o, QString key, ValT&& value) - { - using namespace std::placeholders; - _impl::maybeAdd(bind(&QJsonObject::insert, o, _1, _2), - key, value); - } - - template - inline void addToQuery(QUrlQuery& query, QString key, ValT&& value) + template + inline void addParam(ContT& container, const QString& key, ValT&& value) { - using namespace std::placeholders; - _impl::maybeAdd( - [&query] (QString k, auto&& jsonValue) { - query.addQueryItem(k, jsonValue.toString()); - }, key, value); + _impl::AddNode, Force> + ::impl(container, key, std::forward(value)); } - - template - inline void addToQuery(QUrlQuery& query, QString key, QString value) - { - if (Force || !value.isEmpty()) - query.addQueryItem(key, value); - } - - template - inline void addToQuery(QUrlQuery& query, QString key, bool value) - { - query.addQueryItem(key, - value ? QStringLiteral("true") : QStringLiteral("false")); - } - } // namespace QMatrixClient -- cgit v1.2.3