From c5d06cf378e820ca4290998a5580e87957daf061 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sat, 26 May 2018 20:17:34 +0900 Subject: lib/csapi/: Don't send parameters that were omitted This is important because payloads that include omitted parameters may be malformed. Closes #208 (an example of such malformed payload). --- lib/converters.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 5 deletions(-) (limited to 'lib/converters.h') diff --git a/lib/converters.h b/lib/converters.h index 4cf51cbd..1d1686cd 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -24,6 +24,12 @@ #include #include +#if 0 // Waiting for C++17 +#include + +template +using optional = std::experimental::optional; +#endif // Enable std::unordered_map namespace std @@ -43,9 +49,9 @@ namespace QMatrixClient inline QJsonValue toJson(const QJsonValue& val) { return val; } inline QJsonObject toJson(const QJsonObject& o) { return o; } inline QJsonArray toJson(const QJsonArray& arr) { return arr; } -#ifdef _MSC_VER // MSVC gets lost and doesn't know which overload to use - inline QJsonValue toJson(const QString& s) { return s; } -#endif + // Special-case QStrings so that we could use isEmpty() on them + // (see _impl::AddNote<> below) + inline QString toJson(const QString& s) { return s; } template inline QJsonArray toJson(const std::vector& vals) @@ -70,9 +76,9 @@ namespace QMatrixClient return QJsonArray::fromStringList(strings); } - inline QJsonValue toJson(const QByteArray& bytes) + inline QString toJson(const QByteArray& bytes) { - return QJsonValue(bytes.constData()); + return bytes.constData(); } template @@ -93,6 +99,17 @@ namespace QMatrixClient return json; } +#if 0 + template + inline auto toJson(const optional& optVal) + { + if (optVal) + return toJson(optVal.value()); + + return decltype(toJson(std::declval()))(); + } +#endif + template struct FromJson { @@ -232,4 +249,54 @@ namespace QMatrixClient return h; } }; + + // Conditional insertion into a QJsonObject + + namespace _impl + { + // This one is for types that don't have isEmpty() + template + struct AddNode + { + static void impl(QJsonObject& o, QString key, JsonT&& value) + { + o.insert(std::move(key), std::forward(value)); + } + }; + + // This one is for types that have isEmpty() + template + struct AddNode().isEmpty())> + { + static void impl(QJsonObject& o, QString key, JsonT&& value) + { + if (!value.isEmpty()) + o.insert(std::move(key), std::forward(value)); + } + }; + } + + static constexpr bool IfNotEmpty = false; + + template + inline void addToJson(QJsonObject& o, QString key, ValT&& value) + { + auto&& json = toJson(std::forward(value)); + // QJsonValue doesn't have isEmpty and consumes all other types + // (QString, QJsonObject etc.). + _impl::AddNode> + ::impl(o, std::move(key), std::move(json)); + } + + /** Construct an "omitted" value of a given type + * This is a workaround for the time being while we're not C++17 and + * cannot use `optional`. + */ + template + inline T omitted() + { + T val; + val.omitted = true; + return val; + } } // namespace QMatrixClient -- cgit v1.2.3