aboutsummaryrefslogtreecommitdiff
path: root/lib/converters.h
AgeCommit message (Collapse)Author
2022-09-10Adjust converters.h logic to support Qt 6.4Alexey Rusakov
There's a bit convoluted stack of calls involved here, worth laying out. C++ containers are loaded from JSON containers by calling fromJson<> on each element of the JSON container, specialised by the element type of the C++ container. If that element type is not itself an object (e.g., QString), the respective specialisation of fromJson<> is supposed to kick-in and override the default template that delegates the conversion to JsonConverter (which in turn falls back to JsonObjectConverter unless specialised for that type). Because template functions cannot be partially specialised, that specialised overload for, say, QString, is not complete: it accepts QJsonValue but anything except QJsonValue will hit the generic overload instead. That makes the whole fromJson<> machinery quite sensitive to the exact JSON type passed to it; but as of Qt 5, the types actually presented to fromJson() were limited to QJsonValue and QJsonDocument (okay, QJsonObject and QJsonArray could also be there but the QJsonObject case is trivial for JsonConverter and containers loaded from QJsonArray are all caught with JsonArrayConverter). Qt 6 started returning (const) QJsonValueRef from `QJson*::const_iterator::operator*()` - meaning that whenever a simple type (like, again, QString) is loaded within the bigger container, the "wrong" fromJson() gets called. To fix this, JsonObjectUnpacker gained a dedicated function to unpack QJsonValueRef. QJsonValueRef is an old name existing since Qt 5.15 - no big pain. However, in Qt 6.4 QJsonValueConstRef is getting introduced for the same purpose. It's possible to wrap the *Ref overloads in some #if/#else brackets but at that point it becomes easier to just produce QJsonValue from whatever QJson* iterators dereference to.
2022-08-01Fix FTBFSAlexey Rusakov
2022-08-01Pull out common JsonConverter code to JsonObjectUnpackerAlexey Rusakov
2022-07-12converters.*: facilities to convert enumsAlexey Rusakov
This introduces enumTo/FromJsonString() and flagTo/FromJsonString(), four facility functions to simplify conversion between C++ enums and JSON, and refactors a couple of places where it's useful.
2022-07-12fromJson()/toJson() refactoringAlexey Rusakov
fromJson() is generalised to accept any JSON-like type while passing QJsonObject to JsonConverter<>::load (instead of doLoad). This allows to (still) rely on JsonConverter<> as a customisation point while providing an opportunity to overload fromJson for custom types in a pointed way (specifically, by providing the overload for `fromJson(const QJsonObject&)`), instead of having to go with full-blown JsonConverter<> specialisation. This will be used in a further commit to simplify ReceiptEvent definition. Using if constexpr in combination with constraints (`requires()`) - the first such case in Quotient codebase - allowed to put the entire logic in a single JsonConverter<>::load() body instead of having a facility JsonExporter<> class for SFINAE. Aside from that, fromJson<QJsonValue, QJsonValue> is entirely dropped because it's not supposed to be used that way (it's no-op after all); reflecting that, Event::unsignedPart() and Event::contentPart() no more default to QJsonValue as the expected return type, you have to explicitly provide the type instead (and as one can see from the changes in the commit, it's actually better that way since it's better to validate the value inside JSON - e.g. check QString or QJsonObject for emptiness - than the QJsonValue envelope which may still wrap an empty value). toJson() is also generalised, replacing 3 functions with one that has a constexpr if to discern between two kinds of types.
2022-06-24Code cleanup and reformattingAlexey Rusakov
2022-06-23Drop QUOTIENT_API where it's undueAlexey Rusakov
2022-06-18Drop pre-Qt 5.15 codeAlexey Rusakov
2022-05-31Merge branch 'dev' into update-api-updateAlexey Rusakov
2022-05-31Tweak QOlmAccount and data structures aroundAlexey Rusakov
This is mainly to plug the definition of a string-to-variant map for one-time keys (see https://spec.matrix.org/v1.2/client-server-api/#key-algorithms) into the CS API generated code (see the "shortcut OneTimeKeys" commit for gtad.yaml); but along with it came considerable streamlining of code in qolmaccount.cpp. Using std::variant to store that map also warranted converters.h to gain support for that type (even wider than toJson() that is already in dev - a non-trivial merge from dev is in order).
2022-05-29Refactor EncryptedFile and EC::FileInfo::fileAlexey Rusakov
Besides having a misleading name (and it goes back to the spec), EncryptedFile under `file` key preempts the `url` (or `thumbnail_url`) string value so only one of the two should exist. This is a case for using std::variant<> - despite its clumsy syntax, it can actually simplify and streamline code when all the necessary bits are in place (such as conversion to JSON and getting the common piece - the URL - out of it). This commit replaces `FileInfo::url` and `FileInfo::file` with a common field `source` of type `FileSourceInfo` that is an alias for a variant type covering both underlying types; and `url()` is reintroduced as a function instead, to allow simplified access to whichever URL is available inside the variant. Oh, and EncryptedFile is EncryptedFileMetadata now, to clarify that it does not represent the file payload itself but rather the data necessary to obtain that payload.
2022-05-14Cleanup across the boardAlexey Rusakov
Mainly driven by clang-tidy and SonarCloud warnings (sadly, SonarCloud doesn't store historical reports so no link can be provided here).
2022-05-08toSnakeCase and EventContent::SingleKeyValueAlexey Rusakov
This is a rework of EventContent::SimpleContent previously defined in simplestateevents.h. Quite a few events (and not only state events) have just a single key-value pair in their content - this structure (which is really just a template wrapper around the value) and the accompanying JsonConverter<> specialisation encapsulate the concept to streamline definition of such events. This commit only has simplestateevents.h using it; further commits will use SingleKeyValue in other places. toSnakeCase is a facility function that converts camelCase used for C++ variables into snake_case used in JSON payloads. Combined with the preprocessor trick that makes a string literal from an identifier, this allows to reduce boilerplate code that repeats the same name for fields in C++ event classes and fields in JSON. SingleKeyValue uses it, and there are other cases for it coming.
2022-02-11Enable to/fromJson to work with non-assignable objectsAlexey Rusakov
Previously you could not use toJson() on a polymorphic structure such as one of those defined in eventcontent.h because it is not assignable and the default specialisation of JsonObjectConverter used assignment. To avoid that limitation, one had to specialise JsonObjectConverter for each descendant of EventContent::Base, which is a lot of boilerplate. The new JsonConverter (the template underpinning the "default" to/fromJson implementation) improves on two things: 1. dump() allows to construct your own QJsonObject - or anything else convertable to QJsonValue - instead of requiring to fill in the pre-constructed one. 2. load() allows to construct your value type directly from QJsonObject instead of default-constructing it in advance.
2022-01-23converters.h: slightly clearer code in _impl::addToAlexey Rusakov
2022-01-23Omittable: split out from util.h and refreshAlexey Rusakov
Improvements: - Quotient::lift() - a way to invoke a function on an optional (including Omittable) or a pointer if it's 'truthy'. Doesn't need enhanced function_traits<>, only the standard library; works on any number of arguments that can be dereferenced and casted to bool. - then() - the version of lift() as a member function. - edit() was renamed to ensure() (edit() might become a read-write counterpart of then() at some point). It's not really used across libQuotient codebase (or elsewhere) but is staying there just in case. It can also accept an initializer, removing the requirement of default-constructibility. - Quotient::merge() is simplified, with one universal implementation covering both Omittable/optional and plain values. - All that now lives in its dedicated pair of files, further decluttering util.h
2022-01-18Don't use 'static' on top-level/namespace scopeAlexey Rusakov
When internal linkage is necessary, anonymous namespaces fulfil the same purpose in a better way. See also: https://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static
2021-12-29Add QUOTIENT_API throughout non-generated codeAlexey Rusakov
This include all (hopefully) classes/structures and functions that have non-inline definitions, as well as namespaces with Q_NAMESPACE since those have non-inline (as of Qt 5.15) QMetaObject - for that a new macro, QUO_NAMESPACE, has been devised to accommodate the lack of Q_NAMESPACE_EXPORT in Qt before 5.14.
2021-12-02Cleanup on Sonar issuesAlexey Rusakov
2021-11-28Simplify converters.*Alexey Rusakov
There was a lot of excess redirection in fromJson() and toJson() with most of JsonConverter<> specialisations being unnecessary boilerplate. These have been replaced by overloads for toJson() and explicit specialisations for fromJson() wherever possible without breaking the conversion logic.
2021-11-28One more small thing to actually fix CI breakageAlexey Rusakov
It's might look weird; but without making fromJson() a specialisation it becomes an overload next to an implicit specialisation of the template function defined just above, and then loses to that specialisation because it (also) has the perfect match. (would be great if the compiler shaded the implicit specialisation in such cases - alas it's not how the standard works.)
2021-11-28Fix CI breakage caused by the previous commitAlexey Rusakov
2021-11-17Fix QDateTime(QDate) deprecation warningsAlexey Rusakov
2021-11-12Make ReceiptEvent constructible from contentAlexey Rusakov
Makes the Room::P::toJson() code more readable.
2021-11-12Fix a few quirks in converters.hAlexey Rusakov
2021-08-07converters.h: (actually) enable QUrl; drop unused typesAlexey Rusakov
QUrl can now be converted even with QT_NO_URL_CAST_FROM_STRING; and it can also be put to queries. QByteArray did not really need conversion in JSON context; and QJsonObject is/was never used in queries.
2021-06-13Exclude code no more needed with Qt6Alexey Rusakov
2021-01-16Updated copyright statements upon Git auditKitsune Ral
After going through all the files and the history of commits on them it was clear that some copyright statements are obsolete (the code has been overwritten since) and some are missing. This commit tries best to remedy that, along with adding SPDX tags where they were still not used. Also, a minimal SPDX convention is documented for further contributions. Closes #426.
2020-12-26Port existing copyright statement to reuse using licensediggerCarl Schwan
2020-11-08converters.h: add QUrl supportKitsune Ral
2020-07-21converters.*: clean away old cruftKitsune Ral
2019-11-02Compatibility with Qt 5.14Kitsune Ral
2019-11-01Derive Omittable<> from std::optional<>Kitsune Ral
That breaks API all over the place but: 1. The fixes are trivial. 2. More of std:: is used instead of home-baking the same stuff.
2019-09-12Introduce HashQ<> and UnorderedMap<>Kitsune Ral
Invading into std:: is frowned upon, even though legitimate from the C++ standard perspective. Given that it's possible to pass a hash object to unordered_map, it only takes an alias for std::unordered_map to avoid having to specialize std::hash. And besides, a generic compatibility bridge between qHash and std::hash has been long needed. std::hash<QString> in converters.h remains for now; it will be dropped separately when the API files get regenerated to use UnorderedMap.
2019-08-09Namespace: QMatrixClient -> Quotient (with back comp alias)Kitsune Ral
2019-08-02Apply the new brace wrapping to source filesKitsune Ral
2019-08-02Merge branch 'master' into use-clang-formatKitsune Ral
2019-07-31converters.h: fallback to intrusive toJson() for JsonObjectConverter; ↵Kitsune Ral
general improvements Single-argument fromJson<Omittable<T>>() now works as well.
2019-07-31converters.h: more comments; documented addParam<>()Kitsune Ral
[skip ci]
2019-06-24Merge branch 'master' into clang-formatKitsune Ral
# Conflicts: # CMakeLists.txt # lib/avatar.cpp # lib/connection.cpp # lib/connection.h # lib/connectiondata.cpp # lib/csapi/account-data.cpp # lib/csapi/account-data.h # lib/csapi/capabilities.cpp # lib/csapi/capabilities.h # lib/csapi/content-repo.cpp # lib/csapi/create_room.cpp # lib/csapi/filter.cpp # lib/csapi/joining.cpp # lib/csapi/keys.cpp # lib/csapi/list_joined_rooms.cpp # lib/csapi/notifications.cpp # lib/csapi/openid.cpp # lib/csapi/presence.cpp # lib/csapi/pushrules.cpp # lib/csapi/registration.cpp # lib/csapi/room_upgrades.cpp # lib/csapi/room_upgrades.h # lib/csapi/search.cpp # lib/csapi/users.cpp # lib/csapi/versions.cpp # lib/csapi/whoami.cpp # lib/csapi/{{base}}.cpp.mustache # lib/events/accountdataevents.h # lib/events/eventcontent.h # lib/events/roommemberevent.cpp # lib/events/stateevent.cpp # lib/jobs/basejob.cpp # lib/jobs/basejob.h # lib/networkaccessmanager.cpp # lib/networksettings.cpp # lib/room.cpp # lib/room.h # lib/settings.cpp # lib/settings.h # lib/syncdata.cpp # lib/user.cpp # lib/user.h # lib/util.cpp
2019-03-02style: apply .clang-format to all .cpp and .h filesMarc Deop
2018-12-09fromJson, fillFromJson: avoid overwriting pods if the JSON value is undefinedKitsune Ral
2018-12-08Refactor toJson/fillJsonKitsune Ral
Both now use through a common JsonConverter<> template class with its base definition tuned for structs/QJsonObjects and specialisations for non-object types. This new implementation doesn't work with virtual fillJson functions yet (so EventContent classes still use toJson as a member function) and does not cope quite well with non-constructible objects (you have to specialise JsonConverter<> rather than, more intuitively, JsonObjectConverter<>), but overall is more streamlined compared to the previous implementation. It also fixes one important issue that pushed for a rewrite: the previous implementation was not working with structure hierarchies at all so (in particular) the Filter part of CS API was totally disfunctional.
2018-11-14Improvements in commentsKitsune Ral
- registerEventType(): comment the cryptic _ variable - Room::postEvent: document the return value - Room::Private: upgrade comments to doc-comments - even though in Private, they still are helpful to show hints in IDEs. - General cleanup
2018-09-29Prepare for CS API 0.4.0Kitsune Ral
This commit consists of two parts: upgrading the API infrastructure and trivial but sweeping update to the generated files. 1. The API infrastructure (converters.h, *.mustache and some other non-generated files) now can deal with top-level JSON arrays and response inlining; better supports property maps; and gets some formatting fixes in generated code. 2. Generated files now use QJsonValue instead of QJsonObject as a default type to (un)marshall Matrix API data structures, to match the change in the infrastructure above This commit is still using the old Matrix API definitions, before CS API 0.4.0. Getting to CS API 0.4.0 will come next.
2018-09-02Switch tag order from strings to floats, as The Spec preachesKitsune Ral
The Spec wasn't entirely consistent on this until recently but floats actually are used in the wild, rather than strings.
2018-07-28csapi/third_party_lookup.*: Properly pass a variadic (aka exploded) parametersKitsune Ral
Most of the actual change was in the API definition files (thanks to @anoadragon453), plus a converter from a QJsonObject map to the URL query string.
2018-07-11converters.h: overload addTo() for QStringList to fix FTBFS with the new csapiKitsune Ral
2018-07-08Move Omittable<> to util.hKitsune Ral
2018-07-04Event types system remade to be extensibleKitsune Ral
There were two common points that had to be updated every time a new event is introduced: the EventType enumeration and one of 3 doMakeEvent<> specialisations. The new code has a template class, EventFactory<>, that uses a list of static factory methods to create events instead of typelists used in doMakeEvent<>(); the EventType enumeration is replaced with a namespace populated with constants as necessary. In general, EventType is considered a deprecated mechanism altogether; instead, a set of facilities is provided: is<>() to check if an event has a certain type (to replace comparison against an EventType value) and visit<>() to execute actions based on the event type (replacing switch statements over EventType values). Closes #129.