1#if SIMDJSON_SUPPORTS_CONCEPTS
3#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H
4#ifndef SIMDJSON_CONDITIONAL_INCLUDE
5#define SIMDJSON_ONDEMAND_DESERIALIZE_H
6#include "simdjson/generic/ondemand/object.h"
7#include "simdjson/generic/ondemand/array.h"
8#include "simdjson/generic/ondemand/base.h"
13#if SIMDJSON_STATIC_REFLECTION
24template <std::
unsigned_
integral T>
25error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept {
26 using limits = std::numeric_limits<T>;
29 SIMDJSON_TRY(val.get_uint64().get(x));
30 if (x > (limits::max)()) {
33 out =
static_cast<T
>(x);
37template <std::
floating_po
int T>
38error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept {
40 SIMDJSON_TRY(val.get_double().get(x));
41 out =
static_cast<T
>(x);
45template <std::
signed_
integral T>
46error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept {
47 using limits = std::numeric_limits<T>;
50 SIMDJSON_TRY(val.get_int64().get(x));
51 if (x > (limits::max)() || x < (limits::min)()) {
54 out =
static_cast<T
>(x);
63error_code tag_invoke(deserialize_tag,
auto &val,
char &out)
noexcept {
65 SIMDJSON_TRY(val.get_string().get(x));
74template <concepts::constructible_from_
string_view T,
typename ValT>
75error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(std::is_nothrow_constructible_v<T, std::string_view>) {
77 SIMDJSON_TRY(val.get_string().get(str));
90template <concepts::appendable_containers T,
typename ValT>
91error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(
false) {
92 using value_type =
typename std::remove_cvref_t<T>::value_type;
94 deserializable<value_type, ValT>,
95 "The specified type inside the container must itself be deserializable");
97 std::is_default_constructible_v<value_type>,
98 "The specified type inside the container must default constructible.");
99 SIMDJSON_IMPLEMENTATION::ondemand::array arr;
100 if constexpr (std::is_same_v<std::remove_cvref_t<ValT>, SIMDJSON_IMPLEMENTATION::ondemand::array>) {
103 SIMDJSON_TRY(val.get_array().get(arr));
107 if constexpr (concepts::returns_reference<T>) {
108 if (
auto const err = v.get<value_type>().get(concepts::emplace_one(out));
114 if constexpr (
requires { out.pop_back(); }) {
115 static_cast<void>(out.pop_back());
121 if (
auto const err = v.get<value_type>().get(temp); err) {
124 concepts::emplace_one(out, std::move(temp));
135 template <concepts::
string_view_keyed_map T,
typename ValT>
136error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(
false) {
137 using value_type =
typename std::remove_cvref_t<T>::mapped_type;
139 deserializable<value_type, ValT>,
140 "The specified value type inside the container must itself be deserializable");
142 std::is_default_constructible_v<value_type>,
143 "The specified value type inside the container must default constructible.");
144 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
145 SIMDJSON_TRY(val.get_object().get(obj));
146 for (
auto field : obj) {
147 std::string_view key;
148 SIMDJSON_TRY(field.unescaped_key().get(key));
149 value_type this_value;
150 SIMDJSON_TRY(field.value().get<value_type>().get(this_value));
151 [[maybe_unused]] std::pair<typename T::iterator, bool> result = out.emplace(key, this_value);
161template <concepts::
string_view_keyed_map T>
162error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::object &obj, T &out)
noexcept {
163 using value_type =
typename std::remove_cvref_t<T>::mapped_type;
166 for (
auto field : obj) {
167 std::string_view key;
168 SIMDJSON_TRY(field.unescaped_key().get(key));
170 SIMDJSON_IMPLEMENTATION::ondemand::value value_obj;
171 SIMDJSON_TRY(field.value().get(value_obj));
173 value_type this_value;
174 SIMDJSON_TRY(value_obj.get(this_value));
175 out.emplace(
typename T::key_type(key), std::move(this_value));
180template <concepts::
string_view_keyed_map T>
181error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::value &val, T &out)
noexcept {
182 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
183 SIMDJSON_TRY(val.get_object().get(obj));
184 return simdjson::deserialize(obj, out);
187template <concepts::
string_view_keyed_map T>
188error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::document &doc, T &out)
noexcept {
189 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
190 SIMDJSON_TRY(doc.get_object().get(obj));
191 return simdjson::deserialize(obj, out);
194template <concepts::
string_view_keyed_map T>
195error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::document_reference &doc, T &out)
noexcept {
196 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
197 SIMDJSON_TRY(doc.get_object().get(obj));
198 return simdjson::deserialize(obj, out);
216template <concepts::smart_po
inter T,
typename ValT>
217error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::element_type, ValT>) {
218 using element_type =
typename std::remove_cvref_t<T>::element_type;
223 deserializable<element_type, ValT>,
224 "The specified type inside the unique_ptr must itself be deserializable");
226 std::is_default_constructible_v<element_type>,
227 "The specified type inside the unique_ptr must default constructible.");
230 if (ptr ==
nullptr) {
233 SIMDJSON_TRY(val.template get<element_type>(*ptr));
241template <concepts::optional_type T>
242error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::value_type,
decltype(val)>) {
243 using value_type =
typename std::remove_cvref_t<T>::value_type;
247 SIMDJSON_TRY( val.is_null().get(is_null_value) );
256 SIMDJSON_TRY(val.template get<value_type>(out.value()));
261#if SIMDJSON_STATIC_REFLECTION
265constexpr bool user_defined_type = (std::is_class_v<T>
266&& !std::is_same_v<T, std::string> && !std::is_same_v<T, std::string_view> && !concepts::optional_type<T> &&
267!concepts::appendable_containers<T>);
270template <
typename T,
typename ValT>
271 requires(user_defined_type<T> && std::is_class_v<T>)
272error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept {
273 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
274 if constexpr (std::is_same_v<std::remove_cvref_t<ValT>, SIMDJSON_IMPLEMENTATION::ondemand::object>) {
277 SIMDJSON_TRY(val.get_object().get(obj));
279 template for (
constexpr auto mem : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
280 if constexpr (!std::meta::is_const(mem) && std::meta::is_public(mem)) {
281 constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
282 if constexpr (concepts::optional_type<
decltype(out.[:mem:])>) {
284 auto error = obj[key].get(out.[:mem:]);
294 SIMDJSON_TRY(obj[key].get(out.[:mem:]));
302template <
typename T,
typename ValT>
303 requires(std::is_enum_v<T>)
304error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept {
305#if SIMDJSON_STATIC_REFLECTION
306 std::string_view str;
307 SIMDJSON_TRY(val.get_string().get(str));
308 constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
309 template for (
constexpr auto enum_val : enumerators) {
310 if (str == std::meta::identifier_of(enum_val)) {
319 std::underlying_type_t<T> int_val;
320 SIMDJSON_TRY(val.get(int_val));
321 out =
static_cast<T
>(int_val);
326template <
typename simdjson_value,
typename T>
327 requires(user_defined_type<std::remove_cvref_t<T>>)
328error_code tag_invoke(deserialize_tag, simdjson_value &val, std::unique_ptr<T> &out)
noexcept {
330 out = std::make_unique<T>();
335 if (
auto err = val.get(*out)) {
342template <
typename simdjson_value,
typename T>
343 requires(user_defined_type<std::remove_cvref_t<T>>)
344error_code tag_invoke(deserialize_tag, simdjson_value &val, std::shared_ptr<T> &out)
noexcept {
346 out = std::make_shared<T>();
351 if (
auto err = val.get(*out)) {
363error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<bool> &out)
noexcept {
365 SIMDJSON_TRY( val.is_null().get(is_null_value) );
371 out = std::make_unique<bool>();
374 SIMDJSON_TRY(val.get_bool().get(*out));
378error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<int64_t> &out)
noexcept {
380 SIMDJSON_TRY( val.is_null().get(is_null_value) );
386 out = std::make_unique<int64_t>();
389 SIMDJSON_TRY(val.get_int64().get(*out));
393error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<uint64_t> &out)
noexcept {
395 SIMDJSON_TRY( val.is_null().get(is_null_value) );
401 out = std::make_unique<uint64_t>();
404 SIMDJSON_TRY(val.get_uint64().get(*out));
408error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<double> &out)
noexcept {
410 SIMDJSON_TRY( val.is_null().get(is_null_value) );
416 out = std::make_unique<double>();
419 SIMDJSON_TRY(val.get_double().get(*out));
423error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<std::string_view> &out)
noexcept {
425 SIMDJSON_TRY( val.is_null().get(is_null_value) );
431 out = std::make_unique<std::string_view>();
434 SIMDJSON_TRY(val.get_string().get(*out));
442error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<bool> &out)
noexcept {
444 SIMDJSON_TRY( val.is_null().get(is_null_value) );
450 out = std::make_shared<bool>();
453 SIMDJSON_TRY(val.get_bool().get(*out));
457error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<int64_t> &out)
noexcept {
459 SIMDJSON_TRY( val.is_null().get(is_null_value) );
465 out = std::make_shared<int64_t>();
468 SIMDJSON_TRY(val.get_int64().get(*out));
472error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<uint64_t> &out)
noexcept {
474 SIMDJSON_TRY( val.is_null().get(is_null_value) );
480 out = std::make_shared<uint64_t>();
483 SIMDJSON_TRY(val.get_uint64().get(*out));
487error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<double> &out)
noexcept {
489 SIMDJSON_TRY( val.is_null().get(is_null_value) );
495 out = std::make_shared<double>();
498 SIMDJSON_TRY(val.get_double().get(*out));
502error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<std::string_view> &out)
noexcept {
504 SIMDJSON_TRY( val.is_null().get(is_null_value) );
510 out = std::make_shared<std::string_view>();
513 SIMDJSON_TRY(val.get_string().get(*out));
525error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<std::string> &out)
noexcept {
528 SIMDJSON_TRY( val.is_null().get(is_null_value) );
535 out = std::make_unique<std::string>();
537 std::string_view str;
538 SIMDJSON_TRY(val.get_string().get(str));
539 *out = std::string{str};
543error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<std::string> &out)
noexcept {
546 SIMDJSON_TRY( val.is_null().get(is_null_value) );
553 out = std::make_shared<std::string>();
555 std::string_view str;
556 SIMDJSON_TRY(val.get_string().get(str));
557 *out = std::string{str};
561error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<int> &out)
noexcept {
564 SIMDJSON_TRY( val.is_null().get(is_null_value) );
571 out = std::make_unique<int>();
574 SIMDJSON_TRY(val.get_int64().get(temp));
575 *out =
static_cast<int>(temp);
element_type
The actual concrete type of a JSON element This is the type it is most easily cast to with get<>.
The top level simdjson namespace, containing everything the library provides.
error_code
All possible errors returned by simdjson.
@ INCORRECT_TYPE
JSON element has a different type than user expected.
@ NO_SUCH_FIELD
JSON field not found in object.
@ NUMBER_OUT_OF_RANGE
JSON number does not fit in 64 bits.
@ MEMALLOC
Error allocating memory, most likely out of memory.