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;
63template <StdVariant Variant, ObjectBuilder BuilderT>
65variant_from_json_with_builder (
66 const nlohmann::json &j,
68 const BuilderT &builder)
71 j.at (zrythm::utils::serialization::kVariantTypeKey).get<
int> ();
74 nlohmann::json value_json = j;
75 value_json.erase (zrythm::utils::serialization::kVariantTypeKey);
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_copy_constructible_v<StrippedType>)
89 if (value_json.contains (
90 utils::serialization::kVariantNonObjectValueKey))
92 value_json[utils::serialization::kVariantNonObjectValueKey]
93 .get_to (*object_ptr);
99 if constexpr (std::is_pointer_v<Type>)
101 value_json.get_to (*object_ptr);
102 result = object_ptr.release ();
104 else if constexpr (std::is_copy_constructible_v<Type>)
106 value_json.get_to (*object_ptr);
107 result = *object_ptr;
109 else if constexpr (is_derived_from_template_v<QObjectUniquePtr, Type>)
111 Type t = std::move (*object_ptr);
112 value_json.get_to (*t);
113 result = std::move (t);
117 DEBUG_TEMPLATE_PARAM (Type)
120 "Only variant of pointers or copy-constructible types is currently supported");
125 (create_type_if_current_index.template operator()<I> (), ...);
130 var = creator (std::make_index_sequence<std::variant_size_v<Variant>>{});
138template <
typename T>
struct adl_serializer<T *>
140 static void to_json (json &j,
const T * ptr)
152template <
typename... Args>
struct adl_serializer<std::variant<Args...>>
154 static void to_json (json &j, std::variant<Args...>
const &v)
158 j[zrythm::utils::serialization::kVariantTypeKey] = v.index ();
160 json value_json = std::forward<decltype (value)> (value);
161 if (value_json.is_object ())
163 j.update (value_json);
167 j[zrythm::utils::serialization::kVariantNonObjectValueKey] =
176template <
typename T>
struct adl_serializer<std::unique_ptr<T>>
178 static void to_json (json &json_value,
const std::unique_ptr<T> &ptr)
186 json_value =
nullptr;
189 static void from_json (
const json &json_value, std::unique_ptr<T> &ptr)
190 requires std::is_default_constructible_v<T>
192 ptr = std::make_unique<T> ();
193 json_value.get_to (*ptr);
198template <
typename T>
struct adl_serializer<std::shared_ptr<T>>
200 static void to_json (json &json_value,
const std::shared_ptr<T> &ptr)
208 json_value =
nullptr;
211 static void from_json (
const json &json_value, std::shared_ptr<T> &ptr)
212 requires std::is_default_constructible_v<T>
214 ptr = std::make_shared<T> ();
215 json_value.get_to (*ptr);
220template <
typename T>
struct adl_serializer<zrythm::utils::QObjectUniquePtr<T>>
231 json_value =
nullptr;
236 requires std::is_default_constructible_v<T>
239 json_value.get_to (*ptr);
244template <StrongTypedef T>
struct adl_serializer<T>
246 static void to_json (json &json_value,
const T &strong_type)
248 json_value = type_safe::get (strong_type);
250 static void from_json (
const json &json_value, T &strong_type)
252 json_value.get_to (type_safe::get (strong_type));
256template <
typename Key,
typename T>
257struct adl_serializer<boost::unordered::concurrent_flat_map<Key, T>>
259 using ConcurrentHashMap = boost::unordered::concurrent_flat_map<Key, T>;
261 static void to_json (json &j,
const ConcurrentHashMap &map)
263 std::map<Key, T> temp;
264 map.visit_all ([&temp] (
const auto &kv) {
265 temp.emplace (kv.first, kv.second);
270 static void from_json (
const json &j, ConcurrentHashMap &map)
272 auto temp = j.get<std::map<Key, T>> ();
274 for (
const auto &kv : temp)
276 map.emplace (kv.first, kv.second);
282template <
typename Unit,
typename Rep>
283struct adl_serializer<au::Quantity<Unit, Rep>>
285 static void to_json (json &j,
const au::Quantity<Unit, Rep> &quantity)
287 j = quantity.in (Unit{});
290 static void from_json (
const json &j, au::Quantity<Unit, Rep> &quantity)
293 j.get_to (raw_value);
294 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.