Realm C++ SDK Version v2.2.0

managed_mixed.hpp

1
2//
3// Copyright 2024 Realm Inc.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
18
19#ifndef CPPREALM_MANAGED_MIXED_HPP
20#define CPPREALM_MANAGED_MIXED_HPP
21
22#include <cpprealm/macros.hpp>
23#include <cpprealm/rbool.hpp>
24#include <cpprealm/types.hpp>
25
26namespace realm {
27 template <typename T>
28 struct managed<T, std::enable_if_t<realm::internal::type_info::MixedPersistableConcept<T>::value>> : public managed_base {
29 using managed<T>::managed_base::operator=;
30
31 enum stored_type {
32 Int = 0,
33 Bool = 1,
34 String = 2,
35 Binary = 4,
36 Mixed = 6,
37 Timestamp = 8,
38 Float = 9,
39 Double = 10,
40 Decimal = 11,
41 Link = 12,
42 LinkList = 13,
43 ObjectId = 15,
44 TypedLink = 16,
45 UUID = 17,
46 Null = 18,
47 };
48
49 managed& operator =(const T& v) {
50 m_obj->set(m_key, std::visit([](auto&& arg) {
51 using M = typename internal::type_info::type_info<std::decay_t<decltype(arg)>>::internal_type;
52 return internal::bridge::mixed(M(arg));
53 }, v));
54 return *this;
55 }
56
57 template<typename U>
58 managed& operator =(const U& v) {
59 m_obj->set(m_key, internal::bridge::mixed(v));
60 return *this;
61 }
62
63 [[nodiscard]] stored_type get_stored_type() const {
64 auto val = m_obj->get<realm::internal::bridge::mixed>(m_key);
65 if (val.is_null()) {
66 return stored_type::Null;
67 } else {
68 return static_cast<stored_type>(val.type());
69 }
70 }
71
72 [[nodiscard]] T detach() const {
73 return deserialize<T>(m_obj->get<realm::internal::bridge::mixed>(m_key));
74 }
75
76 [[nodiscard]] T operator *() const {
77 return detach();
78 }
79
80 //MARK: - comparison operators
81 rbool operator==(const T& rhs) const noexcept {
82 if (this->m_rbool_query) {
83 return this->m_rbool_query->mixed_equal(m_key, serialize(rhs));
84 }
85 return detach() == rhs;
86 }
87
88 rbool operator!=(const T& rhs) const noexcept {
89 if (this->m_rbool_query) {
90 return this->m_rbool_query->mixed_not_equal(m_key, serialize(rhs));
91 }
92 return detach() != rhs;
93 }
94
95 rbool operator==(const std::nullopt_t&) const noexcept {
96 if (this->m_rbool_query) {
97 return this->m_rbool_query->mixed_equal(m_key, internal::bridge::mixed(std::monostate()));
98 }
99 return detach() == T(std::monostate());
100 }
101
102 rbool operator!=(const std::nullopt_t&) const noexcept {
103 if (this->m_rbool_query) {
104 return this->m_rbool_query->mixed_not_equal(m_key, internal::bridge::mixed(std::monostate()));
105 }
106 return detach() != T(std::monostate());
107 }
108
109 bool has_link() const {
110 return (get_stored_type() == stored_type::TypedLink);
111 }
112
113 template<typename U>
114 typename managed<U>::ref_type get_stored_link() const {
115 m_realm->read_group();
117
118 auto obj = internal::bridge::object(*m_realm, m.operator internal::bridge::obj_link());
119 uint32_t alternative_key = m_realm->table_for_object_type(managed<std::remove_pointer_t<U>>::schema.name).get_key();
120 uint32_t stored_table = obj.get_obj().get_table().get_key();
121
122 if (alternative_key != stored_table) {
123 throw std::runtime_error("Different link type stored in mixed type. Stored type: " + obj.get_object_schema().get_name());
124 }
125 return typename managed<U>::ref_type(managed<std::remove_pointer_t<U>>(obj.get_obj(), *m_realm));
126 }
127
128 template <typename U>
129 void set_link(U &&v) {
130 static_assert(sizeof(managed<U>), "Must declare schema for T");
131 static_assert(managed<U>::object_type == ObjectType::TopLevel, "Mixed properties can only store Top Level objects.");
132 auto table = m_realm->table_for_object_type(managed<U>::schema.name);
134 if constexpr (managed<U>::schema.HasPrimaryKeyProperty) {
135 auto pk = v.*(managed<U>::schema.primary_key().ptr);
136 o = table.create_object_with_primary_key(realm::internal::bridge::mixed(serialize(pk.value)));
137 } else {
138 o = table.create_object();
139 }
140
141 std::apply([&o, &v, this](auto && ...p) {
142 (accessor<typename std::decay_t<decltype(p)>::Result>::set(
143 o, o.get_table().get_column_key(p.name), *this->m_realm, v.*(std::decay_t<decltype(p)>::ptr)
144 ), ...);
145 }, managed<U>::schema.ps);
146 m_obj->set(m_key, internal::bridge::mixed(o.get_link()));
147 }
148
149 template<typename U>
150 std::enable_if_t<managed<U>::is_object && managed<U>::object_type == ObjectType::TopLevel, void>
151 set_link(managed<U>& link) {
152 m_obj->set(m_key, internal::bridge::mixed(internal::bridge::obj_link(link.m_obj.get_table().get_key(), link.m_obj.get_key())));
153 }
154
155 private:
156 managed() = default;
157 managed(const managed&) = delete;
158 managed(managed &&) = delete;
159 managed& operator=(const managed&) = delete;
160 managed& operator=(managed&&) = delete;
161 template<typename, typename>
162 friend struct managed;
163 };
164
165 template<typename T, typename Types>
166 bool holds_alternative(const realm::managed<Types>& v) noexcept {
167 auto val = v.get_stored_type();
168 switch (val) {
170 if constexpr (std::is_same_v<T, int64_t>)
171 return true;
172 break;
174 if constexpr (std::is_same_v<T, bool>)
175 return true;
176 break;
178 if constexpr (std::is_same_v<T, std::string>)
179 return true;
180 break;
182 if constexpr (std::is_same_v<T, std::vector<uint8_t>>)
183 return true;
184 break;
186 if constexpr (std::is_same_v<T, Types>)
187 return true;
188 break;
190 if constexpr (std::is_same_v<T, std::chrono::time_point<std::chrono::system_clock>>)
191 return true;
192 break;
194 if constexpr (std::is_same_v<T, float>)
195 return true;
196 break;
198 if constexpr (std::is_same_v<T, double>)
199 return true;
200 break;
202 if constexpr (std::is_same_v<T, realm::decimal128>)
203 return true;
204 break;
206 if constexpr (std::is_same_v<T, realm::object_id>)
207 return true;
208 break;
209
211 if constexpr (std::is_same_v<T, realm::uuid>)
212 return true;
213 break;
215 if constexpr (std::is_same_v<T, std::monostate>)
216 return true;
217 break;
219 if constexpr (std::is_pointer_v<T>) {
220 auto m = v.m_obj->template get<internal::bridge::mixed>(v.m_key);
221 uint32_t alternative_key = v.m_realm->table_for_object_type(managed<std::remove_pointer_t<T>>::schema.name).get_key();
222 uint32_t stored_key = internal::bridge::object(*v.m_realm, m.operator internal::bridge::obj_link()).get_object_schema().table_key();
223 return alternative_key == stored_key;
224 }
225 break;
226 }
229 break;
230 default:
231 break;
232 }
233
234 return false;
235 }
236}
237
238#endif//CPPREALM_MANAGED_MIXED_HPP
Definition: rbool.hpp:36
Definition: accessors.hpp:33
Definition: mixed.hpp:69
Definition: obj.hpp:123
Definition: object.hpp:154
Definition: macros.hpp:286
Definition: obj.hpp:62