From b79f67919e05698a8c3daffbe0fe53fa1ce46e54 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 8 May 2022 17:43:08 +0200 Subject: toSnakeCase and EventContent::SingleKeyValue 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. --- lib/events/simplestateevents.h | 72 ++++++++++++++++-------------------------- lib/events/single_key_value.h | 27 ++++++++++++++++ 2 files changed, 55 insertions(+), 44 deletions(-) create mode 100644 lib/events/single_key_value.h (limited to 'lib/events') diff --git a/lib/events/simplestateevents.h b/lib/events/simplestateevents.h index 9610574b..33221542 100644 --- a/lib/events/simplestateevents.h +++ b/lib/events/simplestateevents.h @@ -4,63 +4,47 @@ #pragma once #include "stateevent.h" +#include "single_key_value.h" namespace Quotient { -namespace EventContent { - template - struct SimpleContent { - using value_type = T; - - // The constructor is templated to enable perfect forwarding - template - SimpleContent(QString keyName, TT&& value) - : value(std::forward(value)), key(std::move(keyName)) - {} - SimpleContent(const QJsonObject& json, QString keyName) - : value(fromJson(json[keyName])), key(std::move(keyName)) - {} - QJsonObject toJson() const - { - return { { key, Quotient::toJson(value) } }; - } - - T value; - const QString key; - }; -} // namespace EventContent - -#define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ValueType, _ContentKey) \ - class QUOTIENT_API _Name \ - : public StateEvent> { \ - public: \ - using value_type = content_type::value_type; \ - DEFINE_EVENT_TYPEID(_TypeId, _Name) \ - template \ - explicit _Name(T&& value) \ - : StateEvent(typeId(), matrixTypeId(), QString(), \ - QStringLiteral(#_ContentKey), std::forward(value)) \ - {} \ - explicit _Name(QJsonObject obj) \ - : StateEvent(typeId(), std::move(obj), \ - QStringLiteral(#_ContentKey)) \ - {} \ - auto _ContentKey() const { return content().value; } \ - }; \ - REGISTER_EVENT_TYPE(_Name) \ +#define DEFINE_SIMPLE_STATE_EVENT(_Name, _TypeId, _ValueType, _ContentKey) \ + constexpr auto _Name##Key = #_ContentKey##_ls; \ + class QUOTIENT_API _Name \ + : public StateEvent< \ + EventContent::SingleKeyValue<_ValueType, &_Name##Key>> { \ + public: \ + using value_type = _ValueType; \ + DEFINE_EVENT_TYPEID(_TypeId, _Name) \ + template \ + explicit _Name(T&& value) \ + : StateEvent(TypeId, matrixTypeId(), QString(), \ + std::forward(value)) \ + {} \ + explicit _Name(QJsonObject obj) \ + : StateEvent(TypeId, std::move(obj)) \ + {} \ + auto _ContentKey() const { return content().value; } \ + }; \ + REGISTER_EVENT_TYPE(_Name) \ // End of macro DEFINE_SIMPLE_STATE_EVENT(RoomNameEvent, "m.room.name", QString, name) DEFINE_SIMPLE_STATE_EVENT(RoomTopicEvent, "m.room.topic", QString, topic) -DEFINE_SIMPLE_STATE_EVENT(RoomPinnedEvent, "m.room.pinned_messages", QStringList, pinnedEvents) +DEFINE_SIMPLE_STATE_EVENT(RoomPinnedEvent, "m.room.pinned_messages", + QStringList, pinnedEvents) +constexpr auto RoomAliasesEventKey = "aliases"_ls; class [[deprecated( "m.room.aliases events are deprecated by the Matrix spec; use" " RoomCanonicalAliasEvent::altAliases() to get non-authoritative aliases")]] // -RoomAliasesEvent : public StateEvent> { +RoomAliasesEvent + : public StateEvent< + EventContent::SingleKeyValue> +{ public: DEFINE_EVENT_TYPEID("m.room.aliases", RoomAliasesEvent) explicit RoomAliasesEvent(const QJsonObject& obj) - : StateEvent(typeId(), obj, QStringLiteral("aliases")) + : StateEvent(typeId(), obj) {} QString server() const { return stateKey(); } QStringList aliases() const { return content().value; } diff --git a/lib/events/single_key_value.h b/lib/events/single_key_value.h new file mode 100644 index 00000000..75ca8cd2 --- /dev/null +++ b/lib/events/single_key_value.h @@ -0,0 +1,27 @@ +#pragma once + +#include "converters.h" + +namespace Quotient { + +namespace EventContent { + template + struct SingleKeyValue { + T value; + }; +} // namespace EventContent + +template +struct JsonConverter> { + using content_type = EventContent::SingleKeyValue; + static content_type load(const QJsonValue& jv) + { + return { fromJson(jv.toObject().value(JsonKey)) }; + } + static QJsonObject dump(const content_type& c) + { + return { { JsonKey, toJson(c.value) } }; + } + static inline const auto JsonKey = toSnakeCase(*KeyStr); +}; +} // namespace Quotient -- cgit v1.2.3