typeextractors.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #ifndef QTJSONSERIALIZER_TYPEEXTRACTORS_H
  2. #define QTJSONSERIALIZER_TYPEEXTRACTORS_H
  3. #include "typeconverter.h"
  4. #include <optional>
  5. #include <tuple>
  6. #include <variant>
  7. #include <QtCore/qbytearray.h>
  8. #include <QtCore/qpair.h>
  9. namespace QtJsonSerializer::TypeExtractors {
  10. template <template <typename> class TSmartPointer, typename TType>
  11. class SmartPointerExtractor final : public TypeExtractor
  12. {
  13. public:
  14. using Pointer = TType*;
  15. using Type = TSmartPointer<TType>;
  16. QByteArray baseType() const final {
  17. return QByteArrayLiteral("pointer");
  18. }
  19. QList<int> subtypes() const final {
  20. return {qMetaTypeId<Pointer>()};
  21. }
  22. QVariant extract(const QVariant &value, int) const final {
  23. return QVariant::fromValue<Pointer>(value.value<Type>().get());
  24. }
  25. void emplace(QVariant &target, const QVariant &value, int) const final {
  26. target = QVariant::fromValue(Type{value.value<Pointer>()});
  27. }
  28. };
  29. template <typename TType>
  30. class SmartPointerExtractor<QPointer, TType> final : public TypeExtractor
  31. {
  32. static_assert(std::is_base_of_v<QObject, TType>, "QPointer can only handle QObject types");
  33. public:
  34. using Pointer = TType*;
  35. using Type = QPointer<TType>;
  36. QByteArray baseType() const final {
  37. return QByteArrayLiteral("qpointer");
  38. }
  39. QList<int> subtypes() const final {
  40. return {qMetaTypeId<Pointer>()};
  41. }
  42. QVariant extract(const QVariant &value, int) const final {
  43. return QVariant::fromValue<Pointer>(value.value<Type>().data());
  44. }
  45. void emplace(QVariant &target, const QVariant &value, int) const final {
  46. target = QVariant::fromValue(Type{value.value<Pointer>()});
  47. }
  48. };
  49. template <template <typename, typename> class TPair, typename TFirst, typename TSecond>
  50. class PairExtractor final : public TypeExtractor
  51. {
  52. public:
  53. using Type = TPair<TFirst, TSecond>;
  54. QByteArray baseType() const final {
  55. return QByteArrayLiteral("pair");
  56. }
  57. QList<int> subtypes() const final {
  58. return {qMetaTypeId<TFirst>(), qMetaTypeId<TSecond>()};
  59. }
  60. QVariant extract(const QVariant &value, int index) const final {
  61. const auto vPair = value.value<Type>();
  62. switch (index) {
  63. case 0:
  64. return QVariant::fromValue(vPair.first);
  65. case 1:
  66. return QVariant::fromValue(vPair.second);
  67. default:
  68. return {};
  69. }
  70. }
  71. void emplace(QVariant &target, const QVariant &value, int index) const final {
  72. Q_ASSERT(target.userType() == qMetaTypeId<Type>());
  73. const auto vPair = reinterpret_cast<Type*>(target.data());
  74. switch (index) {
  75. case 0:
  76. vPair->first = value.value<TFirst>();
  77. break;
  78. case 1:
  79. vPair->second = value.value<TSecond>();
  80. break;
  81. default:
  82. break;
  83. }
  84. }
  85. };
  86. template <typename TValue>
  87. class OptionalExtractor final : public TypeExtractor
  88. {
  89. public:
  90. using Type = std::optional<TValue>;
  91. QByteArray baseType() const final {
  92. return QByteArrayLiteral("optional");
  93. }
  94. QList<int> subtypes() const final {
  95. return {qMetaTypeId<TValue>()};
  96. }
  97. QVariant extract(const QVariant &value, int) const final {
  98. if (const auto opt = value.value<std::optional<TValue>>(); opt)
  99. return QVariant::fromValue(*opt);
  100. else
  101. return QVariant::fromValue(nullptr);
  102. }
  103. void emplace(QVariant &target, const QVariant &value, int) const final {
  104. if (value.isNull())
  105. target = QVariant::fromValue<std::optional<TValue>>(std::nullopt);
  106. else
  107. target = QVariant::fromValue<std::optional<TValue>>(value.value<TValue>());
  108. }
  109. };
  110. template <typename... TValues>
  111. class TupleExtractor final : public TypeExtractor
  112. {
  113. public:
  114. using Type = std::tuple<TValues...>;
  115. private:
  116. template <size_t Index>
  117. inline QVariant getIf(const Type &, size_t) const {
  118. return {};
  119. }
  120. template <size_t Index, typename TValue, typename... TRest>
  121. inline QVariant getIf(const Type &tpl, size_t index) const {
  122. if (Index == index)
  123. return QVariant::fromValue(std::get<Index>(tpl));
  124. else
  125. return getIf<Index + 1, TRest...>(tpl, index);
  126. }
  127. template <size_t Index>
  128. inline void setIf(Type *, size_t, const QVariant &) const {}
  129. template <size_t Index, typename TValue, typename... TRest>
  130. inline void setIf(Type *tpl, size_t index, const QVariant &value) const {
  131. if (Index == index)
  132. std::get<Index>(*tpl) = value.value<TValue>();
  133. else
  134. setIf<Index + 1, TRest...>(tpl, index, value);
  135. }
  136. public:
  137. QByteArray baseType() const final {
  138. return QByteArrayLiteral("tuple");
  139. }
  140. QList<int> subtypes() const final {
  141. return {qMetaTypeId<TValues>()...};
  142. }
  143. QVariant extract(const QVariant &value, int index) const final {
  144. return getIf<0, TValues...>(value.value<Type>(), static_cast<size_t>(index));
  145. }
  146. void emplace(QVariant &target, const QVariant &value, int index) const final {
  147. Q_ASSERT(target.userType() == qMetaTypeId<Type>());
  148. setIf<0, TValues...>(reinterpret_cast<Type*>(target.data()), static_cast<size_t>(index), value);
  149. }
  150. };
  151. template <typename... TValues>
  152. class VariantExtractor final : public TypeExtractor
  153. {
  154. public:
  155. using Type = std::variant<TValues...>;
  156. private:
  157. template <typename _>
  158. inline Type constructIfType(const QVariant &) const { return {}; }
  159. template <typename _, typename TValue, typename... TArgs>
  160. inline Type constructIfType(const QVariant &var) const {
  161. if (var.userType() == qMetaTypeId<TValue>())
  162. return var.value<TValue>();
  163. else
  164. return constructIfType<_, TArgs...>(var);
  165. }
  166. public:
  167. QByteArray baseType() const final {
  168. return QByteArrayLiteral("variant");
  169. }
  170. QList<int> subtypes() const final {
  171. return {qMetaTypeId<TValues>()...};
  172. }
  173. QVariant extract(const QVariant &value, int) const final {
  174. return std::visit([](const auto &x) {
  175. return QVariant::fromValue(x);
  176. }, value.value<Type>());
  177. }
  178. void emplace(QVariant &target, const QVariant &value, int) const final {
  179. target = QVariant::fromValue(constructIfType<void, TValues...>(value));
  180. }
  181. };
  182. }
  183. #endif // QTJSONSERIALIZER_TYPEEXTRACTORS_H