8#include "StringLiterals.h"
18namespace QXmpp::Private::Enums {
23template<
class T, std::size_t N, std::size_t... I>
24constexpr std::array<std::remove_cv_t<T>, N> to_array_impl(T (&&a)[N], std::index_sequence<I...>)
26 return { { std::move(a[I])... } };
31template<
typename Enum, std::
size_t N>
32consteval std::array<std::remove_cv_t<std::tuple<Enum, QStringView>>, N> makeValues(std::tuple<Enum, QStringView> (&&a)[N])
34 return detail::to_array_impl(std::move(a), std::make_index_sequence<N> {});
37template<
typename Enum>
41template<
typename Enum,
size_t N>
42consteval bool checkEnumOrder(
const std::array<std::tuple<Enum, QStringView>, N> &values)
45 if constexpr (N > 0) {
46 offset = size_t(std::get<0>(values[0]));
48 for (
size_t i = offset; i < (N + offset); ++i) {
49 if (i !=
size_t(std::get<0>(values[i]))) {
56template<
typename Enum>
57concept SerializableEnum =
requires {
60 requires std::ranges::random_access_range<
decltype(Data<Enum>::Values)>;
61 requires std::same_as<
62 std::ranges::range_value_t<
decltype(Data<Enum>::Values)>,
63 std::tuple<Enum, QStringView>>;
64 requires checkEnumOrder<Enum>(Data<Enum>::Values);
67template<
typename Enum>
68concept SerializableFlags =
requires {
70 requires Data<Enum>::IsFlags ==
true;
72 requires std::ranges::random_access_range<
decltype(Data<Enum>::Values)>;
73 requires std::same_as<
74 std::ranges::range_value_t<
decltype(Data<Enum>::Values)>,
75 std::tuple<Enum, QStringView>>;
78template<
typename Enum>
79concept NullableEnum =
requires(Enum value) {
81 { Data<Enum>::NullValue } -> std::convertible_to<Enum>;
84template<
typename Enum>
85constexpr std::optional<Enum> fromString(QStringView str)
86 requires SerializableEnum<Enum> || SerializableFlags<Enum>
88 constexpr auto values = Data<Enum>::Values;
90 auto enumPart = [](
const auto &v) {
return std::get<0>(v); };
91 auto stringPart = [](
const auto &v) {
return std::get<1>(v); };
93 if (
auto itr = std::ranges::find(values, str, stringPart); itr != values.end()) {
94 return enumPart(*itr);
99template<SerializableEnum Enum>
100constexpr QStringView toStringView(Enum value)
103 constexpr auto offset = size_t(std::get<0>(Data<Enum>::Values[0]));
105 auto &[enumerator, string] = Data<Enum>::Values.at(
size_t(value) - offset);
109template<SerializableEnum Enum>
110inline QString toString(Enum value)
112 return staticString(toStringView(value));
115template<SerializableFlags Enum,
typename Container>
116constexpr QFlags<Enum> fromStrings(
const Container &container)
119 for (
const auto &
string : container) {
120 if (
auto flag = fromString<Enum>(
string)) {
121 result.setFlag(*flag);
127template<SerializableFlags Enum>
128constexpr auto toStrings(QFlags<Enum> value)
130 auto testFlag = [value](
auto entry) {
131 auto &[enumerator, string] = entry;
132 return value.testFlag(enumerator);
134 auto string = [](
auto entry) {
return std::get<1>(entry); };
136 return std::views::filter(Data<Enum>::Values, testFlag) | std::views::transform(
string);
139template<SerializableFlags Enum>
140QList<QString> toStringList(QFlags<Enum> value)
142 auto strings = toStrings(value) | std::views::transform([](QStringView sv) {
return staticString(sv); });
143 return QList<QString>(strings.begin(), strings.end());
150template<QXmpp::Private::Enums::SerializableEnum Enum>
151bool operator==(QStringView s, Enum e) {
return s == QXmpp::Private::Enums::toStringView(e); }
152template<QXmpp::Private::Enums::SerializableEnum Enum>
153bool operator!=(QStringView s, Enum e) {
return s != QXmpp::Private::Enums::toStringView(e); }
155template<QXmpp::Private::Enums::SerializableEnum Enum>
156struct QConcatenable<Enum> {
158 typedef QString ConvertTo;
159 enum { ExactSize =
true };
161 static int size(Enum e)
163 return QXmpp::Private::Enums::toStringView(e).size();
165 static void appendTo(Enum m, QChar *&out)
167 QConcatenable<QStringView>::appendTo(QXmpp::Private::Enums::toStringView(m), out);
171template<QXmpp::Private::Enums::SerializableEnum Enum>
172QDebug operator<<(QDebug debug, Enum e)
174 return debug << QXmpp::Private::Enums::toStringView(e);