21 template<
class T, std::size_t N, std::size_t... I>
22 constexpr std::array<std::remove_cv_t<T>, N> to_array_impl(T (&&a)[N], std::index_sequence<I...>)
24 return { { std::move(a[I])... } };
29 template<
typename Enum, std::
size_t N>
30 consteval std::array<std::remove_cv_t<std::tuple<Enum, QStringView>>, N> makeValues(std::tuple<Enum, QStringView> (&&a)[N])
32 return detail::to_array_impl(std::move(a), std::make_index_sequence<N> {});
35 template<
typename Enum>
39 template<
typename Enum,
size_t N>
40 consteval
bool checkEnumOrder(
const std::array<std::tuple<Enum, QStringView>, N> &values)
43 if constexpr (N > 0) {
44 offset = size_t(std::get<0>(values[0]));
46 for (
size_t i = offset; i < (N + offset); ++i) {
47 if (i !=
size_t(std::get<0>(values[i]))) {
54 template<
typename Enum>
55 concept SerializableEnum = requires {
58 requires std::ranges::random_access_range<decltype(Data<Enum>::Values)>;
59 requires std::same_as<
60 std::ranges::range_value_t<decltype(Data<Enum>::Values)>,
61 std::tuple<Enum, QStringView>>;
62 requires checkEnumOrder<Enum>(Data<Enum>::Values);
65 template<
typename Enum>
66 concept SerializableFlags = requires {
68 requires Data<Enum>::IsFlags ==
true;
70 requires std::ranges::random_access_range<decltype(Data<Enum>::Values)>;
71 requires std::same_as<
72 std::ranges::range_value_t<decltype(Data<Enum>::Values)>,
73 std::tuple<Enum, QStringView>>;
76 template<
typename Enum>
77 concept NullableEnum = requires(Enum value) {
79 { Data<Enum>::NullValue } -> std::convertible_to<Enum>;
82 template<
typename Enum>
83 constexpr std::optional<Enum> fromString(QStringView str)
84 requires SerializableEnum<Enum> || SerializableFlags<Enum>
86 constexpr
auto values = Data<Enum>::Values;
88 auto enumPart = [](
const auto &v) {
return std::get<0>(v); };
89 auto stringPart = [](
const auto &v) {
return std::get<1>(v); };
91 if (
auto itr = std::ranges::find(values, str, stringPart); itr != values.end()) {
92 return enumPart(*itr);
97 template<SerializableEnum Enum>
98 constexpr QStringView toString(Enum value)
101 constexpr
auto offset = size_t(std::get<0>(Data<Enum>::Values[0]));
103 auto &[enumerator, string] = Data<Enum>::Values.at(
size_t(value) - offset);
107 template<SerializableFlags Enum,
typename Container>
108 constexpr QFlags<Enum> fromStrings(
const Container &container)
111 for (
const auto &
string : container) {
112 if (
auto flag = fromString<Enum>(
string)) {
113 result.setFlag(*flag);
119 template<SerializableFlags Enum>
120 constexpr
auto toStrings(QFlags<Enum> value)
122 auto testFlag = [value](
auto entry) {
123 auto &[enumerator, string] = entry;
124 return value.testFlag(enumerator);
126 auto string = [](
auto entry) {
return std::get<1>(entry); };
128 return std::views::filter(Data<Enum>::Values, testFlag) | std::views::transform(
string);
131 template<SerializableFlags Enum>
132 QList<QString> toStringList(QFlags<Enum> value)
134 auto strings = toStrings(value) | std::views::transform(&QStringView::toString);
135 return QList<QString>(strings.begin(), strings.end());
142 template<QXmpp::Private::Enums::SerializableEnum Enum>
143 bool operator==(QStringView s, Enum e) {
return s == QXmpp::Private::Enums::toString(e); }
144 template<QXmpp::Private::Enums::SerializableEnum Enum>
145 bool operator!=(QStringView s, Enum e) {
return s != QXmpp::Private::Enums::toString(e); }
147 template<QXmpp::Private::Enums::SerializableEnum Enum>
148 struct QConcatenable<Enum> {
150 typedef QString ConvertTo;
151 enum { ExactSize =
true };
153 static int size(Enum e)
155 return QXmpp::Private::Enums::toString(e).size();
157 static void appendTo(Enum m, QChar *&out)
159 QConcatenable<QStringView>::appendTo(QXmpp::Private::Enums::toString(m), out);
163 template<QXmpp::Private::Enums::SerializableEnum Enum>
164 QDebug operator<<(QDebug debug, Enum e)
166 return debug << QXmpp::Private::Enums::toString(e);