16namespace QXmpp::Private::Enums {
21template<
class T, std::size_t N, std::size_t... I>
22constexpr std::array<std::remove_cv_t<T>, N> to_array_impl(T (&&a)[N], std::index_sequence<I...>)
24 return { { std::move(a[I])... } };
29template<
typename Enum, std::
size_t N>
30consteval 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> {});
35template<
typename Enum>
39template<
typename Enum,
size_t N>
40consteval 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]))) {
54template<
typename Enum>
55concept 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);
65template<
typename Enum>
66concept 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>>;
76template<
typename Enum>
77concept NullableEnum =
requires(Enum value) {
79 { Data<Enum>::NullValue } -> std::convertible_to<Enum>;
82template<
typename Enum>
83constexpr 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);
97template<SerializableEnum Enum>
98constexpr 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);
107template<SerializableFlags Enum,
typename Container>
108constexpr QFlags<Enum> fromStrings(
const Container &container)
111 for (
const auto &
string : container) {
112 if (
auto flag = fromString<Enum>(
string)) {
113 result.setFlag(*flag);
119template<SerializableFlags Enum>
120constexpr 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);
131template<SerializableFlags Enum>
132QList<QString> toStringList(QFlags<Enum> value)
134 auto strings = toStrings(value) | std::views::transform(&QStringView::toString);
135 return QList<QString>(strings.begin(), strings.end());
142template<QXmpp::Private::Enums::SerializableEnum Enum>
143bool operator==(QStringView s, Enum e) {
return s == QXmpp::Private::Enums::toString(e); }
144template<QXmpp::Private::Enums::SerializableEnum Enum>
145bool operator!=(QStringView s, Enum e) {
return s != QXmpp::Private::Enums::toString(e); }
147template<QXmpp::Private::Enums::SerializableEnum Enum>
148struct 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);
163template<QXmpp::Private::Enums::SerializableEnum Enum>
164QDebug operator<<(QDebug debug, Enum e)
166 return debug << QXmpp::Private::Enums::toString(e);