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