9#include "utils/exceptions.h"
11#include "utils/traits.h"
12#include "utils/types.h"
17#include <boost/unordered/concurrent_flat_map_fwd.hpp>
18#include <nlohmann/json.hpp>
23to_json (nlohmann::json &j,
const QString &s)
28from_json (
const nlohmann::json &j, QString &s)
30 s = QString::fromUtf8 (j.get<std::string> ());
34to_json (nlohmann::json &j,
const QUuid &uuid)
36 j = uuid.toString (QUuid::WithoutBraces);
39from_json (
const nlohmann::json &j, QUuid &uuid)
41 uuid = QUuid::fromString (j.get<QString> ());
44namespace zrythm::utils::serialization
47static constexpr auto kSchemaVersionKey =
"schemaVersion"sv;
48static constexpr auto kAppVersionKey =
"appVersion"sv;
49static constexpr auto kDocumentTypeKey =
"documentType"sv;
50static constexpr auto kVariantTypeKey =
"type"sv;
51static constexpr auto kVariantNonObjectValueKey =
"nonObjectValue"sv;
67template <StdVariant Variant, ObjectBuilder BuilderT>
69variant_create_object_only (
70 const nlohmann::json &j,
72 const BuilderT &builder)
75 j.at (zrythm::utils::serialization::kVariantTypeKey).get<
int> ();
77 auto creator = [&]<
size_t... I> (std::index_sequence<I...>) {
80 auto create_type_if_current_index = [&]<
size_t N> () {
81 using Type = std::variant_alternative_t<N, Variant>;
82 using StrippedType = std::remove_pointer_t<Type>;
85 auto object_ptr = builder.template build<StrippedType> ();
87 if constexpr (std::is_pointer_v<Type>)
88 result = object_ptr.release ();
89 else if constexpr (std::is_copy_constructible_v<Type>)
91 else if constexpr (is_derived_from_template_v<QObjectUniquePtr, Type>)
92 result = std::move (*object_ptr);
95 DEBUG_TEMPLATE_PARAM (Type)
98 "Only variant of pointers or copy-constructible types is currently supported");
103 (create_type_if_current_index.template operator()<I> (), ...);
108 var = creator (std::make_index_sequence<std::variant_size_v<Variant>>{});
121template <StdVariant Variant>
123variant_deserialize_data (
const nlohmann::json &j, Variant &var)
126 nlohmann::json value_json = j;
127 value_json.erase (zrythm::utils::serialization::kVariantTypeKey);
131 using ObjType = std::decay_t<
decltype (obj)>;
132 if constexpr (std::is_pointer_v<ObjType>)
134 if (value_json.contains (kVariantNonObjectValueKey))
135 value_json[kVariantNonObjectValueKey].get_to (*obj);
137 value_json.get_to (*obj);
139 else if constexpr (is_derived_from_template_v<QObjectUniquePtr, ObjType>)
141 if (value_json.contains (kVariantNonObjectValueKey))
142 value_json[kVariantNonObjectValueKey].get_to (*obj);
144 value_json.get_to (*obj);
148 if (value_json.contains (kVariantNonObjectValueKey))
149 value_json[kVariantNonObjectValueKey].get_to (obj);
151 value_json.get_to (obj);
171template <StdVariant Variant, ObjectBuilder BuilderT>
173variant_from_json_with_builder (
174 const nlohmann::json &j,
176 const BuilderT &builder)
178 variant_create_object_only (j, var, builder);
179 variant_deserialize_data (j, var);
187template <
typename T>
struct adl_serializer<T *>
189 static void to_json (json &j,
const T * ptr)
201template <
typename... Args>
struct adl_serializer<std::variant<Args...>>
203 static void to_json (json &j, std::variant<Args...>
const &v)
207 j[zrythm::utils::serialization::kVariantTypeKey] = v.index ();
209 json value_json = std::forward<decltype (value)> (value);
210 if (value_json.is_object ())
212 j.update (value_json);
216 j[zrythm::utils::serialization::kVariantNonObjectValueKey] =
225template <
typename T>
struct adl_serializer<std::unique_ptr<T>>
227 static void to_json (json &json_value,
const std::unique_ptr<T> &ptr)
235 json_value =
nullptr;
238 static void from_json (
const json &json_value, std::unique_ptr<T> &ptr)
239 requires std::is_default_constructible_v<T>
241 ptr = std::make_unique<T> ();
242 json_value.get_to (*ptr);
247template <
typename T>
struct adl_serializer<std::shared_ptr<T>>
249 static void to_json (json &json_value,
const std::shared_ptr<T> &ptr)
257 json_value =
nullptr;
260 static void from_json (
const json &json_value, std::shared_ptr<T> &ptr)
261 requires std::is_default_constructible_v<T>
263 ptr = std::make_shared<T> ();
264 json_value.get_to (*ptr);
269template <
typename T>
struct adl_serializer<zrythm::utils::QObjectUniquePtr<T>>
280 json_value =
nullptr;
285 requires std::is_default_constructible_v<T>
288 json_value.get_to (*ptr);
293template <StrongTypedef T>
struct adl_serializer<T>
295 static void to_json (json &json_value,
const T &strong_type)
297 json_value = type_safe::get (strong_type);
299 static void from_json (
const json &json_value, T &strong_type)
301 json_value.get_to (type_safe::get (strong_type));
305template <
typename Key,
typename T>
306struct adl_serializer<boost::unordered::concurrent_flat_map<Key, T>>
308 using ConcurrentHashMap = boost::unordered::concurrent_flat_map<Key, T>;
310 static void to_json (json &j,
const ConcurrentHashMap &map)
312 std::map<Key, T> temp;
313 map.visit_all ([&temp] (
const auto &kv) {
314 temp.emplace (kv.first, kv.second);
319 static void from_json (
const json &j, ConcurrentHashMap &map)
321 auto temp = j.get<std::map<Key, T>> ();
323 for (
const auto &kv : temp)
325 map.emplace (kv.first, kv.second);
331template <
typename Unit,
typename Rep>
332struct adl_serializer<au::Quantity<Unit, Rep>>
334 static void to_json (json &j,
const au::Quantity<Unit, Rep> &quantity)
336 j = quantity.in (Unit{});
339 static void from_json (
const json &j, au::Quantity<Unit, Rep> &quantity)
342 j.get_to (raw_value);
343 quantity = au::QuantityMaker<Unit>{}(raw_value);
A unique pointer for QObject objects that also works with QObject-based ownership.
Base class for exceptions in Zrythm.