6 #include <Quotient/converters.h>
7 #include <Quotient/function_traits.h>
13 template <
typename EventT>
14 using event_ptr_tt = std::unique_ptr<EventT>;
18 constexpr inline auto TypeKey =
"type"_ls;
19 constexpr inline auto BodyKey =
"body"_ls;
20 constexpr inline auto ContentKey =
"content"_ls;
21 constexpr inline auto EventIdKey =
"event_id"_ls;
22 constexpr inline auto SenderKey =
"sender"_ls;
23 constexpr inline auto RoomIdKey =
"room_id"_ls;
24 constexpr inline auto UnsignedKey =
"unsigned"_ls;
25 constexpr inline auto RedactedCauseKey =
"redacted_because"_ls;
26 constexpr inline auto PrevContentKey =
"prev_content"_ls;
27 constexpr inline auto StateKeyKey =
"state_key"_ls;
29 using event_type_t = QLatin1String;
35 template <
typename EventT,
typename BaseEventT = Event>
36 concept EventClass = std::derived_from<EventT, BaseEventT>;
38 template <EventClass EventT>
39 bool is(
const Event& e);
49 const char*
const className;
50 const AbstractEventMetaType*
const baseType;
51 const event_type_t matrixId;
54 explicit AbstractEventMetaType(
const char* className,
55 AbstractEventMetaType* nearestBase =
nullptr,
56 const char* matrixId =
nullptr)
57 : className(className), baseType(nearestBase), matrixId(matrixId)
60 nearestBase->addDerived(
this);
63 void addDerived(
const AbstractEventMetaType* newType);
65 virtual ~AbstractEventMetaType() =
default;
69 template <
class EventT>
70 friend class EventMetaType;
74 virtual bool doLoadFrom(
const QJsonObject& fullJson,
const QString& type,
75 Event*& event)
const = 0;
78 std::vector<
const AbstractEventMetaType*> derivedTypes{};
79 Q_DISABLE_COPY_MOVE(AbstractEventMetaType)
84 inline bool operator==(
const AbstractEventMetaType& lhs,
85 const AbstractEventMetaType& rhs)
100 template <
class EventT>
105 using AbstractEventMetaType::AbstractEventMetaType;
137 event_ptr_tt<EventT> loadFrom(
const QJsonObject& fullJson,
138 const QString& type)
const
140 Event* event =
nullptr;
141 const bool goodEnough = doLoadFrom(fullJson, type, event);
142 if (!event && goodEnough)
143 return event_ptr_tt<EventT>{
new EventT(fullJson) };
144 return event_ptr_tt<EventT>{
static_cast<EventT*>(event) };
148 bool doLoadFrom(
const QJsonObject& fullJson,
const QString& type,
149 Event*& event)
const override
151 if constexpr (requires { EventT::TypeId; }) {
152 if (EventT::TypeId != type)
155 for (
const auto& p : derivedTypes) {
156 p->doLoadFrom(fullJson, type, event);
158 Q_ASSERT(is<EventT>(*event));
163 if constexpr (requires { EventT::isValid; }) {
164 if (!EventT::isValid(fullJson))
166 }
else if constexpr (!requires { EventT::TypeId; })
168 event =
new EventT(fullJson);
179 template <EventClass EventT,
typename... ArgTs>
180 inline event_ptr_tt<EventT> makeEvent(ArgTs&&... args)
182 return std::make_unique<EventT>(std::forward<ArgTs>(args)...);
185 template <EventClass EventT>
186 constexpr const auto& mostSpecificMetaType()
188 if constexpr (requires { EventT::MetaType; })
189 return EventT::MetaType;
191 return EventT::BaseMetaType;
199 template <EventClass EventT>
200 inline event_ptr_tt<EventT> loadEvent(
const QJsonObject& fullJson)
202 return mostSpecificMetaType<EventT>().loadFrom(
203 fullJson, fullJson[TypeKey].toString());
211 template <EventClass EventT>
212 inline event_ptr_tt<EventT> loadEvent(
const QString& matrixType,
213 const auto&... otherBasicJsonParams)
215 return mostSpecificMetaType<EventT>().loadFrom(
216 EventT::basicJson(matrixType, otherBasicJsonParams...), matrixType);
219 template <EventClass EventT>
220 struct JsonConverter<event_ptr_tt<EventT>>
221 : JsonObjectUnpacker<event_ptr_tt<EventT>> {
224 using JsonObjectUnpacker<event_ptr_tt<EventT>>::load;
225 static auto load(
const QJsonObject& jo)
227 return loadEvent<EventT>(jo);
235 static inline EventMetaType<Event> BaseMetaType {
"Event" };
236 virtual const AbstractEventMetaType& metaType()
const
241 Q_DISABLE_COPY(Event)
242 Event(Event&&)
noexcept =
default;
243 Event& operator=(Event&&) =
delete;
247 static QJsonObject basicJson(
const QString& matrixType,
248 const QJsonObject& content)
250 return { { TypeKey, matrixType }, { ContentKey, content } };
254 QString matrixType()
const;
256 template <EventClass EventT>
259 return Quotient::is<EventT>(*
this);
290 template <
typename... VisitorTs>
291 auto switchOnType(VisitorTs&&... visitors)
const;
293 const QJsonObject& fullJson()
const {
return _json; }
302 const QJsonObject contentJson()
const;
309 template <
typename T,
typename KeyT>
310 const T contentPart(KeyT&& key)
const
312 return fromJson<T>(contentJson()[std::forward<KeyT>(key)]);
315 const QJsonObject unsignedJson()
const;
322 template <
typename T,
typename KeyT>
323 const T unsignedPart(KeyT&& key)
const
325 return fromJson<T>(unsignedJson()[std::forward<KeyT>(key)]);
330 const QDebugStateSaver _dss { dbg };
331 dbg.noquote().nospace()
332 << e.matrixType() <<
'(' << e.metaType().className <<
"): ";
340 bool isStateEvent()
const;
343 friend class EventMetaType<Event>;
345 explicit Event(
const QJsonObject& json);
347 QJsonObject& editJson() {
return _json; }
348 virtual void dumpTo(QDebug dbg)
const;
353 using EventPtr = event_ptr_tt<Event>;
355 template <EventClass EventT>
356 using EventsArray = std::vector<event_ptr_tt<EventT>>;
357 using Events = EventsArray<Event>;
378 template <
typename EventT, EventClass BaseEventT,
typename ContentT =
void>
379 class EventTemplate :
public BaseEventT {
384 !std::is_same_v<ContentT,
void>,
385 "If you see this, you tried to use EventTemplate with the default"
386 " ContentT type, which is void. This default is only used with explicit"
387 " specialisations (see CallEvent, e.g.). Otherwise, if you don't intend"
388 " to use the content part of EventTemplate then you don't need"
389 " EventTemplate; just use the base event class directly");
390 using content_type = ContentT;
392 explicit EventTemplate(
const QJsonObject& json)
395 explicit EventTemplate(
const ContentT& c)
396 : BaseEventT(EventT::basicJson(EventT::TypeId, toJson(c)))
399 ContentT content()
const {
return fromJson<ContentT>(
this->contentJson()); }
411 #define QUO_BASE_EVENT(CppType_, BaseCppType_, ...)
412 friend class EventMetaType<CppType_>;
413 static inline EventMetaType<CppType_> BaseMetaType{
414 #CppType_, &BaseCppType_::BaseMetaType __VA_OPT__(, ) __VA_ARGS__
416 static_assert(&CppType_::BaseMetaType == &BaseMetaType,
417 #CppType_ " is wrong here - check for copy-pasta");
418 const AbstractEventMetaType& metaType() const override
439 #define QUO_EVENT(CppType_, MatrixType_)
440 friend class EventMetaType<CppType_>;
441 static inline const EventMetaType<CppType_> MetaType{ #CppType_,
444 static_assert(&CppType_::MetaType == &MetaType,
445 #CppType_ " is wrong here - check for copy-pasta");
446 static inline const auto& TypeId = MetaType.matrixId;
447 const AbstractEventMetaType& metaType() const override
453 #define QUO_CONTENT_GETTER_X(PartType_, PartName_, JsonKey_)
454 PartType_ PartName_() const
456 static const auto PartName_##JsonKey = JsonKey_;
457 return contentPart<PartType_>(PartName_##JsonKey);
468 #define QUO_CONTENT_GETTER(PartType_, PartName_)
479 #define DEFINE_SIMPLE_EVENT(Name_, Base_, TypeId_, ValueType_, GetterName_,
481 constexpr inline auto Name_##ContentKey = JsonKey_##_ls;
483 : public EventTemplate<
485 EventContent::SingleKeyValue<ValueType_, Name_##ContentKey>> {
488 using value_type = ValueType_;
489 using EventTemplate::EventTemplate;
496 template <EventClass EventT>
497 inline bool is(
const Event& e)
500 static_assert(requires { &EventT::metaType; },
501 "Event class doesn't have a public metaType() override - "
502 "did you misplace the QUO_*EVENT macro?");
503 if constexpr (requires { EventT::MetaType; }) {
504 return &e.metaType() == &EventT::MetaType;
506 const auto* p = &e.metaType();
508 if (p == &EventT::BaseMetaType)
510 }
while ((p = p->baseType) !=
nullptr);
522 template <EventClass EventT,
typename BasePtrT>
523 inline auto eventCast(
const BasePtrT& eptr)
524 ->
decltype(
static_cast<EventT*>(std::to_address(eptr)))
526 return eptr && is<std::decay_t<EventT>>(*eptr)
527 ?
static_cast<EventT*>(std::to_address(eptr))
545 template <EventClass EventT,
typename BaseEventT>
546 inline auto eventCast(event_ptr_tt<BaseEventT>&& eptr)
548 return eptr && is<std::decay_t<EventT>>(*eptr)
549 ? event_ptr_tt<EventT>(
static_cast<EventT*>(eptr.release()))
554 template <
typename FnT,
typename BaseT>
555 concept Invocable_With_Downcast = requires
557 requires EventClass<BaseT>;
558 std::is_base_of_v<BaseT, std::remove_cvref_t<fn_arg_t<FnT>>>;
562 template <EventClass BaseT,
typename TailT>
563 inline auto switchOnType(
const BaseT& event, TailT&& tail)
565 if constexpr (std::is_invocable_v<TailT, BaseT>) {
567 }
else if constexpr (_impl::Invocable_With_Downcast<TailT, BaseT>) {
568 using event_type = fn_arg_t<TailT>;
569 if (is<std::decay_t<event_type>>(event))
570 return tail(
static_cast<event_type>(event));
571 return std::invoke_result_t<TailT, event_type>();
573 return std::forward<TailT>(tail);
577 template <
typename FnT1,
typename... FnTs>
578 inline auto switchOnType(
const EventClass
auto& event, FnT1&& fn1, FnTs&&... fns)
580 using event_type1 = fn_arg_t<FnT1>;
581 if (is<std::decay_t<event_type1>>(event))
582 return fn1(
static_cast<event_type1>(event));
583 return switchOnType(event, std::forward<FnTs>(fns)...);
586 template <
typename... VisitorTs>
587 inline auto Event::switchOnType(VisitorTs&&... visitors)
const
589 return Quotient::switchOnType(*
this,
590 std::forward<VisitorTs>(visitors)...);
594 Q_DECLARE_METATYPE(Quotient::Event*)
595 Q_DECLARE_METATYPE(
const Quotient::Event*)