89 return Visitor::convert (
t, options);
97 static std::optional<var> convert (
const T& t,
const Options& options)
99 constexpr auto fallbackVersion = detail::ForwardingSerialisationTraits<T>::marshallingVersion;
100 const auto versionToUse = options.getExplicitVersion()
101 .value_or (fallbackVersion);
103 if (versionToUse > fallbackVersion)
109 Visitor visitor { versionToUse, options.getVersionIncluded() };
110 detail::doSave (visitor, t);
111 return visitor.value;
114 std::optional<int> getVersion()
const {
return version; }
116 template <
typename... Ts>
117 void operator() (Ts&&... ts)
119 (visit (std::forward<Ts> (ts)), ...);
123 Visitor (
const std::optional<int>& explicitVersion,
bool includeVersion)
124 : version (explicitVersion),
127 if (! (version.has_value() && includeVersion))
130 auto obj = std::make_unique<DynamicObject>();
131 obj->setProperty (
"__version__", *version);
132 return obj.release();
134 versionIncluded (includeVersion) {}
136 template <
typename T>
137 void visit (
const T& t)
139 if constexpr (std::is_integral_v<T>)
143 else if constexpr (std::is_floating_point_v<T>)
147 else if (
auto converted = convert (t))
157 template <
typename T>
158 void visit (
const Named<T>& named)
160 if (! value.has_value())
164 value =
new DynamicObject;
166 auto* obj = value->getDynamicObject();
181 if (! trySetProperty (*obj, named))
185 template <
typename T>
186 void visit (
const SerialisationSize<T>&)
191 void visit (
const bool& t)
196 void visit (
const String& t)
201 void visit (
const var& t)
206 template <
typename T>
207 std::optional<var> convert (
const T& t)
209 return convert (t, Options{}.withVersionIncluded (versionIncluded));
214 if (! value.has_value())
219 else if (
auto* array = value->getArray())
225 template <
typename T>
226 bool trySetProperty (DynamicObject& obj,
const Named<T>& n)
228 if (
const auto converted = convert (n.value))
230 obj.setProperty (Identifier (std::string (n.name)), *converted);
237 std::optional<int> version;
238 std::optional<var> value;
239 bool versionIncluded =
true;
266 template <
typename T>
269 return Visitor::convert<T> (v);
276 template <
typename T>
277 static std::optional<T> convert (
const var& v)
279 const auto version = [&]() -> std::optional<int>
281 if (
auto*
obj = v.getDynamicObject())
282 if (
obj->hasProperty (
"__version__"))
283 return (
int)
obj->getProperty (
"__version__");
288 Visitor visitor { version, v };
290 detail::doLoad (visitor, t);
291 return ! visitor.failed ? std::optional<T> (std::move (t))
295 std::optional<int> getVersion()
const {
return version; }
297 template <
typename... Ts>
298 void operator() (Ts&&... ts)
300 (visit (std::forward<Ts> (ts)), ...);
304 Visitor (std::optional<int> vn,
const var& i)
305 : version (vn), input (i) {}
307 template <
typename T>
310 if constexpr (std::is_integral_v<T>)
312 readPrimitive (std::in_place_type<int64>, t);
314 else if constexpr (std::is_floating_point_v<T>)
316 readPrimitive (std::in_place_type<double>, t);
320 auto node = getNodeToRead();
322 if (! node.has_value())
325 auto converted = convert<T> (*node);
327 if (converted.has_value())
334 template <
typename T>
335 void visit (
const Named<T>& named)
337 auto node = getNodeToRead();
339 if (! node.has_value())
342 auto* obj = node->getDynamicObject();
344 failed = obj ==
nullptr || ! tryGetProperty (*obj, named);
347 template <
typename T>
348 void visit (
const SerialisationSize<T>& t)
355 t.size =
static_cast<T
> (array->size());
356 currentArrayIndex = 0;
366 readPrimitive (std::in_place_type<bool>, t);
369 void visit (String& t)
371 readPrimitive (std::in_place_type<String>, t);
379 static std::optional<double> pullTyped (std::in_place_type_t<double>,
const var& source)
381 return source.isDouble() ? std::optional<double> ((
double) source) : std::nullopt;
384 static std::optional<int64> pullTyped (std::in_place_type_t<int64>,
const var& source)
386 return source.isInt() || source.isInt64() ? std::optional<int64> ((int64) source) : std::nullopt;
389 static std::optional<bool> pullTyped (std::in_place_type_t<bool>,
const var& source)
391 return std::optional<bool> ((
bool) source);
394 static std::optional<String> pullTyped (std::in_place_type_t<String>,
const var& source)
396 return source.isString() ? std::optional<String> (source.toString()) : std::nullopt;
399 std::optional<var> getNodeToRead()
404 if (currentArrayIndex == std::numeric_limits<size_t>::max())
407 const auto* array = input.
getArray();
409 if (array ==
nullptr)
412 if ((
int) currentArrayIndex < array->size())
413 return array->getReference ((
int) currentArrayIndex++);
419 template <
typename TypeToRead,
typename T>
420 void readPrimitive (std::in_place_type_t<TypeToRead> tag, T& t)
422 auto node = getNodeToRead();
424 if (! node.has_value())
427 auto typed = pullTyped (tag, *node);
429 if (typed.has_value())
430 t =
static_cast<T
> (*typed);
435 template <
typename T>
436 static bool tryGetProperty (
const DynamicObject& obj,
const Named<T>& n)
438 const Identifier identifier (String (n.name.data(), n.name.size()));
440 if (! obj.hasProperty (identifier))
443 const auto converted = convert<T> (obj.getProperty (identifier));
445 if (! converted.has_value())
448 n.value = *converted;
452 std::optional<int> version;
454 size_t currentArrayIndex = std::numeric_limits<size_t>::max();