1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QPROTOBUFONEOF_H |
5 | #define QPROTOBUFONEOF_H |
6 | |
7 | #if 0 |
8 | # pragma qt_class(QProtobufOneof) |
9 | #endif |
10 | |
11 | #include <QtProtobuf/qprotobufmessage.h> |
12 | #include <QtProtobuf/qtprotobuftypes.h> |
13 | |
14 | #include <QtCore/qmetatype.h> |
15 | #include <QtCore/qtclasshelpermacros.h> |
16 | #include <QtCore/qvariant.h> |
17 | |
18 | QT_BEGIN_NAMESPACE |
19 | |
20 | namespace QtProtobufPrivate { |
21 | |
22 | class QProtobufOneofPrivate; |
23 | class QProtobufOneof final |
24 | { |
25 | template <typename T> |
26 | using is_oneof_value_type = std::disjunction< |
27 | QtProtobuf::is_protobuf_message_without_ordering<T>, |
28 | QtProtobuf::is_protobuf_non_message<T>>; |
29 | template <typename T> |
30 | using if_oneof_value_type = std::enable_if_t<is_oneof_value_type<T>::value, bool>; |
31 | |
32 | template <typename T> |
33 | using is_oneof_compatible = std::disjunction<QtProtobuf::is_protobuf_message<T>, |
34 | is_oneof_value_type<T>>; |
35 | template <typename T> |
36 | using if_oneof_compatible = std::enable_if_t<is_oneof_compatible<T>::value, bool>; |
37 | |
38 | public: |
39 | Q_PROTOBUF_EXPORT QProtobufOneof(); |
40 | Q_PROTOBUF_EXPORT ~QProtobufOneof(); |
41 | Q_PROTOBUF_EXPORT QProtobufOneof(const QProtobufOneof &other); |
42 | Q_PROTOBUF_EXPORT QProtobufOneof &operator=(const QProtobufOneof &other); |
43 | QProtobufOneof(QProtobufOneof &&other) noexcept : d_ptr(std::exchange(obj&: other.d_ptr, new_val: {})) { } |
44 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QProtobufOneof) |
45 | void swap(QProtobufOneof &other) noexcept |
46 | { |
47 | qt_ptr_swap(lhs&: d_ptr, rhs&: other.d_ptr); |
48 | } |
49 | |
50 | template <typename T, if_oneof_compatible<T> = true> |
51 | void setValue(const T &value, int fieldNumber) |
52 | { |
53 | setValue(QVariant::fromValue<T>(value), fieldNumber); |
54 | } |
55 | |
56 | template<typename T, QtProtobuf::if_protobuf_message<T> = true> |
57 | void setValue(T &&value, int fieldNumber) |
58 | { |
59 | setValue(QVariant::fromValue<T>(std::forward<T>(value)), fieldNumber); |
60 | } |
61 | |
62 | template <typename T, if_oneof_value_type<T> = true> |
63 | T value() const |
64 | { |
65 | ensureMetaType(lhs: QMetaType::fromType<T>(), rhs: rawValue().metaType()); |
66 | return rawValue().value<T>(); |
67 | } |
68 | |
69 | template <typename T, QtProtobuf::if_protobuf_message<T> = true> |
70 | T *message() |
71 | { |
72 | ensureRawValue(metaType: QMetaType::fromType<T>()); |
73 | return static_cast<T *>(rawValue().data()); |
74 | } |
75 | |
76 | template <typename T, QtProtobuf::if_protobuf_message<T> = true> |
77 | const T *message() const |
78 | { |
79 | ensureMetaType(lhs: QMetaType::fromType<T>(), rhs: rawValue().metaType()); |
80 | return static_cast<const T *>(rawValue().data()); |
81 | } |
82 | |
83 | template <typename T, if_oneof_value_type<T> = true> |
84 | bool isEqual(const T &otherValue, int fieldNumber) const |
85 | { |
86 | return this->fieldNumber() == fieldNumber |
87 | && QMetaType::fromType<T>() == rawValue().metaType() && value<T>() == otherValue; |
88 | } |
89 | |
90 | template <typename T, QtProtobuf::if_protobuf_message<T> = true> |
91 | bool isEqual(const T &otherValue, int fieldNumber) const |
92 | { |
93 | if (this->fieldNumber() != fieldNumber |
94 | || QMetaType::fromType<T>() != rawValue().metaType()) { |
95 | return false; |
96 | } |
97 | |
98 | const auto *messagePtr = message<T>(); |
99 | return messagePtr && *messagePtr == otherValue; |
100 | } |
101 | |
102 | Q_PROTOBUF_EXPORT int fieldNumber() const; |
103 | Q_PROTOBUF_EXPORT bool holdsField(int fieldNumber) const; |
104 | |
105 | private: |
106 | Q_ALWAYS_INLINE static void ensureMetaType(QMetaType lhs, QMetaType rhs) |
107 | { |
108 | Q_ASSERT(lhs == rhs); |
109 | } |
110 | |
111 | Q_PROTOBUF_EXPORT void ensureRawValue(QMetaType metaType); |
112 | |
113 | friend Q_PROTOBUF_EXPORT bool comparesEqual(const QProtobufOneof &lhs, |
114 | const QProtobufOneof &rhs) noexcept; |
115 | Q_DECLARE_EQUALITY_COMPARABLE(QProtobufOneof) |
116 | |
117 | friend class QT_PREPEND_NAMESPACE(QProtobufMessage); |
118 | |
119 | Q_PROTOBUF_EXPORT void setValue(const QVariant &value, int fieldNumber); |
120 | Q_PROTOBUF_EXPORT const QVariant &rawValue() const; |
121 | QVariant &rawValue() |
122 | { |
123 | return const_cast<QVariant &>(std::as_const(t&: *this).rawValue()); |
124 | } |
125 | |
126 | QProtobufOneofPrivate *d_ptr; |
127 | Q_DECLARE_PRIVATE(QProtobufOneof) |
128 | }; |
129 | } // namespace QtProtobufPrivate |
130 | |
131 | QT_END_NAMESPACE |
132 | |
133 | #endif // QPROTOBUFONEOF_H |
134 | |