libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
quotient_common.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2019 Kitsune Ral <Kitsune-Ral@users.sf.net>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
7#include "util.h" // IWYU pragma: keep - for Quotient::Literals::operator""_L1
8
9#include <qobjectdefs.h>
10
11#include <array>
12#include <span>
13#include <QtQmlIntegration/qqmlintegration.h>
14
15//! \brief Quotient replacement for the Q_FLAG/Q_DECLARE_FLAGS combination
16//!
17//! Although the comment in QTBUG-82295 says that Q_FLAG[_NS] "should" be
18//! applied to the enum type only, Qt then doesn't allow to wrap the
19//! corresponding flag type (defined with Q_DECLARE_FLAGS) into a QVariant.
20//! This macro defines Q_FLAG and on top of that adds Q_ENUM_IMPL which is
21//! a part of Q_ENUM() macro that enables the metatype data but goes under
22//! the moc radar to avoid double registration of the same data in the map
23//! defined in moc_*.cpp.
24//!
25//! Simply put, instead of using Q_FLAG/Q_DECLARE_FLAGS combo (and struggling
26//! to figure out what you should pass to Q_FLAG if you want to make it
27//! wrappable in a QVariant) use the macro below, and things will just work.
28//!
29//! \sa https://bugreports.qt.io/browse/QTBUG-82295
30#define QUO_DECLARE_FLAGS(Flags, Enum)
31 Q_DECLARE_FLAGS(Flags, Enum)
32 Q_ENUM_IMPL(Enum)
33 Q_FLAG(Flags)
34
35//! \brief Quotient replacement for the Q_FLAG_NS/Q_DECLARE_FLAGS combination
36//!
37//! This is the equivalent of QUO_DECLARE_FLAGS for enums declared at the
38//! namespace level (be sure to provide Q_NAMESPACE _in the same file_
39//! as the enum definition and this macro).
40//! \sa QUO_DECLARE_FLAGS
41#define QUO_DECLARE_FLAGS_NS(Flags, Enum)
42 Q_DECLARE_FLAGS(Flags, Enum)
43 Q_ENUM_NS_IMPL(Enum)
44 Q_FLAG_NS(Flags)
45
46namespace Quotient {
47Q_NAMESPACE_EXPORT(QUOTIENT_API)
49Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") // Prevent unscoped enums from overwriting each other
50
51//! \brief Enabling structure for conversion between a given enum and JSON
52//!
53//! Providing this structure in a way that satisfies either Serializable_Enum or Serializable_Flag
54//! enables de/serialisation using fromJson() and toJson() for the respective enum. See commented
55//! out code in the definition for an idea what should be there to satisfy either concept. `strings`
56//! has the list of JSON representations for respective enumerators. `defaultValue` should have
57//! the enumerator used when the string coming from JSON cannot be found in `strings`, or when
58//! the JSON value is not even a string. `isFlag` defines whether the enumeration should be treated
59//! as a collection of flag values (usually, such enum also has a QFlags counterpart type defined
60//! with Q_FLAG, Q_FLAG_NS, QUO_DECLARE_FLAGS or QUO_DECLARE_FLAGS_NS). `isFlag` can either be
61//! `false` or completely omitted from the definition for non-flag enumerations.
62//!
63//! \note This mechanism doesn't support using numeric values of enumerators in JSON; if you need
64//! to store and load the numeric value, use fromJson() and toJson() with the underlying
65//! integral type instead of the enumeration type.
66//!
67//! The rules to define enumerations and their string representations are different for non-flag and
68//! flag enumerations - see the respective note blocks below. These cannot be checked at
69//! compile-time, breaking them will lead to either assertion failures or incorrect conversion.
70//!
71//! \note For non-flag enumerations, \p EnumT must not have gaps in enumerators, or \p strings has
72//! to match those gaps (i.e., if \p EnumT is defined as
73//! <tt>{ Value1 = 1, Value2 = 3, Value3 = 5 }</tt> then \p strings should be defined as
74//! <tt>{ "", "Value1", "", "Value2", "", "Value3" }</tt> (mind the gap at value 0,
75//! in particular). Although it is allowed to have enumerations based
76//! \note For flag enumerations, enumerators of \p EnumT must follow the power-of-two sequence
77//! starting from 1, so exactly 1,2,4,8,16 and so on. Having gaps is allowed but the same rule
78//! as for non-flag enumerations applies: \p strings has to reflect this gap, skipping an
79//! array item. As of now, there's no way to encode and decode the value of zero (no flags
80//! set) or a combination of flags (i.e. Flag4|Flag16).
81//!
82//! In most cases you can use facility macros, QUO_META_ENUM and QUO_META_FLAG, instead of writing
83//! all the boilerplate yourself. The enumeration can be defined in any namespace but the macros
84//! are only valid when put into `namespace Quotient`. Clients are free to write
85//! `namespace Quotient { QUO_META_ENUM(...) }` for that matter.
86
87template <typename EnumT>
89{
90 // static constexpr std::array strings{"one"_L1, "two"_L1, "three"_L1};
91 // static constexpr auto defaultValue = EnumT::Undefined;
92 // static constexpr bool isFlag = true; // If the enum should be treated as a flags group
93};
94
95template <typename EnumT>
96concept Serializable_Enum = requires {
97 typename MetaEnum<EnumT>;
100};
101
102template <typename FlagT>
103concept Serializable_Flag = std::is_unsigned_v<std::underlying_type_t<FlagT>>
105
106#define QUO_META_ENUM_IMPL(EnumType_, IsFlag_, DefaultValue_, ...)
107 template <>
108 struct QUOTIENT_API MetaEnum<EnumType_>
109 {
110 static constexpr std::array strings{__VA_ARGS__};
111 static constexpr auto defaultValue = DefaultValue_;
112 static constexpr bool isFlag = IsFlag_;
113 }; // End of macro
114
115#define QUO_META_ENUM(EnumType_, DefaultValue_, ...)
116 QUO_META_ENUM_IMPL(EnumType_, false, DefaultValue_, __VA_ARGS__)
117
118#define QUO_META_FLAG(EnumType_, DefaultValue_, ...)
119 QUO_META_ENUM_IMPL(EnumType_, true, DefaultValue_, __VA_ARGS__)
120
121// TODO: code like below should be generated from the CS API definition
122
123//! \brief Membership states
124//!
125//! These are used for member events. The names here are case-insensitively
126//! equal to state names used on the wire.
127//! \sa MemberEventContent, RoomMemberEvent
128enum class Membership : uint16_t {
129 // Specific power-of-2 values (1,2,4,...) are important here as syncdata.cpp
130 // depends on that, as well as Join being the first in line
131 Invalid = 0x0,
132 Join = 0x1,
133 Leave = 0x2,
134 Invite = 0x4,
135 Knock = 0x8,
136 Ban = 0x10,
138};
140QUO_META_FLAG(Membership, Membership::Invalid, "join"_L1, "leave"_L1, "invite"_L1, "knock"_L1,
141 "ban"_L1)
142
143//! \brief Local user join-state names
144//!
145//! This represents a subset of Membership values that may arrive as the local
146//! user's state grouping for the sync response.
147//! \sa SyncData
148enum class JoinState : std::underlying_type_t<Membership> {
149 Invalid = std::underlying_type_t<Membership>(Membership::Invalid),
150 Join = std::underlying_type_t<Membership>(Membership::Join),
151 Leave = std::underlying_type_t<Membership>(Membership::Leave),
152 Invite = std::underlying_type_t<Membership>(Membership::Invite),
153 Knock = std::underlying_type_t<Membership>(Membership::Knock),
154};
156
157template <>
159{
160 // Same as Membership, except "ban"
161 static constexpr auto strings = std::span(MetaEnum<Membership>::strings).subspan<0, 4>();
162 // Protect against Membership gaining new values without JoinState being revisited
163 static_assert(std::size(strings) + 1 == std::size(MetaEnum<Membership>::strings));
164};
165
166constexpr inline const auto &JoinStateStrings = MetaEnum<JoinState>::strings;
167
168//! \brief Network job running policy flags
169//!
170//! So far only background/foreground flags are available.
171//! \sa Connection::callApi, Connection::run
173Q_ENUM_NS(RunningPolicy)
174
175//! \brief The result of URI resolution using UriResolver
176//! \sa UriResolver
185Q_ENUM_NS(UriResolveResult)
186
187enum class RoomType : uint8_t {
188 Space = 0,
189 Undefined = 0xFF,
190};
191Q_ENUM_NS(RoomType)
193
195 MegolmV1AesSha2 = 0,
196 Undefined = 0xFF,
197};
198Q_ENUM_NS(EncryptionType)
199
200constexpr inline auto MegolmV1AesSha2AlgoKey = "m.megolm.v1.aes-sha2"_L1;
201
203
204//! Enum representing the available room join rules
205enum class JoinRule : uint32_t {
206 Public,
207 Knock,
208 Invite,
209 Private,
212};
213Q_ENUM_NS(JoinRule)
214QUO_META_ENUM(JoinRule, JoinRule::Public, "public"_L1, "knock"_L1, "invite"_L1, "private"_L1,
215 "restricted"_L1, "knock_restricted"_L1)
216
217} // namespace Quotient
218Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask)
219Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates)
RunningPolicy
Network job running policy flags.
Membership
Membership states.
UriResolveResult
The result of URI resolution using UriResolver.
constexpr auto MegolmV1AesSha2AlgoKey
JoinRule
Enum representing the available room join rules.
constexpr const auto & JoinStateStrings
#define QUO_DECLARE_FLAGS_NS(Flags, Enum)
Quotient replacement for the Q_FLAG_NS/Q_DECLARE_FLAGS combination.
#define QUO_META_FLAG(EnumType_, DefaultValue_,...)
#define QUO_META_ENUM_IMPL(EnumType_, IsFlag_, DefaultValue_,...)
#define QUO_META_ENUM(EnumType_, DefaultValue_,...)
#define QUOTIENT_API