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"
14#if SIMDJSON_STATIC_REFLECTION
26template <std::
unsigned_
integral T>
27error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept {
28 using limits = std::numeric_limits<T>;
31 SIMDJSON_TRY(val.get_uint64().get(x));
32 if (x > (limits::max)()) {
35 out =
static_cast<T
>(x);
39template <std::
floating_po
int T>
40error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept {
41 if constexpr (std::is_same_v<T, float>) {
45 return val.get_float().get(out);
46#if SIMDJSON_SUPPORTS_FLOAT32_T
47 }
else if constexpr (std::is_same_v<T, std::float32_t>) {
50 SIMDJSON_TRY(val.get_float().get(x));
51 out =
static_cast<T
>(x);
56 SIMDJSON_TRY(val.get_double().get(x));
57 out =
static_cast<T
>(x);
62template <std::
signed_
integral T>
63error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept {
64 using limits = std::numeric_limits<T>;
67 SIMDJSON_TRY(val.get_int64().get(x));
68 if (x > (limits::max)() || x < (limits::min)()) {
71 out =
static_cast<T
>(x);
80error_code tag_invoke(deserialize_tag,
auto &val,
char &out)
noexcept {
82 SIMDJSON_TRY(val.get_string().get(x));
91template <concepts::constructible_from_
string_view T,
typename ValT>
92error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(std::is_nothrow_constructible_v<T, std::string_view>) {
94 SIMDJSON_TRY(val.get_string().get(str));
95 if constexpr (
requires { out.assign(str.data(), str.size()); }) {
98 out.assign(str.data(), str.size());
105#if SIMDJSON_SUPPORTS_CHAR8_T
108template <concepts::constructible_from_u8
string_view T,
typename ValT>
109error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(std::is_nothrow_constructible_v<T, std::u8string_view>) {
110 std::u8string_view str;
111 SIMDJSON_TRY(val.get_u8string().get(str));
112 if constexpr (
requires { out.assign(str.data(), str.size()); }) {
114 out.assign(str.data(), str.size());
132concept deserialize_in_place =
133 concepts::returns_reference<T> &&
requires(T &c) { c.pop_back(); } &&
134 !std::is_trivially_copyable_v<typename T::value_type> &&
135 (
sizeof(
typename T::value_type) > 32 || concepts::constructible_from_string_view<typename T::value_type>);
139struct pop_back_guard {
143 if (armed) { container.pop_back(); }
155template <concepts::appendable_containers T,
typename ValT>
156error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(
false) {
157 using value_type =
typename std::remove_cvref_t<T>::value_type;
159 deserializable<value_type, ValT>,
160 "The specified type inside the container must itself be deserializable");
162 std::is_default_constructible_v<value_type>,
163 "The specified type inside the container must default constructible.");
164 SIMDJSON_IMPLEMENTATION::ondemand::array arr;
165 if constexpr (std::is_same_v<std::remove_cvref_t<ValT>, SIMDJSON_IMPLEMENTATION::ondemand::array>) {
168 SIMDJSON_TRY(val.get_array().get(arr));
171 if constexpr (std::is_same_v<T, std::vector<value_type>> && !std::is_same_v<value_type, bool>) {
176 struct scratch_space {
177 std::vector<value_type> elements{};
180 static thread_local scratch_space scratch;
181 if (!scratch.busy && out.empty()) {
182 struct release_scratch {
186 bool complete{
false};
189 simdjson_never_inline
void keep_parsed() noexcept {
190 s.elements.resize(parsed);
191 out.swap(s.elements);
194 if (simdjson_unlikely(!complete)) { keep_parsed(); }
197 if (s.elements.capacity() *
sizeof(value_type) > (1 << 20)) { std::vector<value_type>().swap(s.elements); }
200 } release{scratch, out};
203 SIMDJSON_TRY(v.get<value_type>(scratch.elements.emplace_back()));
206 out.reserve(release.parsed);
207 release.complete =
true;
208 for (
auto &e : scratch.elements) { out.emplace_back(std::move(e)); }
212 if constexpr (details::deserialize_in_place<T>) {
214 auto &slot = concepts::emplace_one(out);
217 details::pop_back_guard<T> guard{out};
218 SIMDJSON_TRY(v.get<value_type>(slot));
226 if (
auto const err = v.get<value_type>(temp); err) {
229 concepts::emplace_one(out, std::move(temp));
240 template <concepts::
string_view_keyed_map T,
typename ValT>
241error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(
false) {
242 using value_type =
typename std::remove_cvref_t<T>::mapped_type;
244 deserializable<value_type, ValT>,
245 "The specified value type inside the container must itself be deserializable");
247 std::is_default_constructible_v<value_type>,
248 "The specified value type inside the container must default constructible.");
249 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
250 SIMDJSON_TRY(val.get_object().get(obj));
251 for (
auto field : obj) {
252 std::string_view key;
253 SIMDJSON_TRY(field.unescaped_key().get(key));
254 value_type this_value;
255 SIMDJSON_TRY(field.value().get<value_type>().get(this_value));
256 [[maybe_unused]] std::pair<typename T::iterator, bool> result = out.emplace(key, this_value);
266template <concepts::
string_view_keyed_map T>
267error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::object &obj, T &out)
noexcept(
false) {
268 using value_type =
typename std::remove_cvref_t<T>::mapped_type;
271 for (
auto field : obj) {
272 std::string_view key;
273 SIMDJSON_TRY(field.unescaped_key().get(key));
275 SIMDJSON_IMPLEMENTATION::ondemand::value value_obj;
276 SIMDJSON_TRY(field.value().get(value_obj));
278 value_type this_value;
279 SIMDJSON_TRY(value_obj.get(this_value));
280 out.emplace(
typename T::key_type(key), std::move(this_value));
285template <concepts::
string_view_keyed_map T>
286error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::value &val, T &out)
noexcept(
false) {
287 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
288 SIMDJSON_TRY(val.get_object().get(obj));
289 return simdjson::deserialize(obj, out);
292template <concepts::
string_view_keyed_map T>
293error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::document &doc, T &out)
noexcept(
false) {
294 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
295 SIMDJSON_TRY(doc.get_object().get(obj));
296 return simdjson::deserialize(obj, out);
299template <concepts::
string_view_keyed_map T>
300error_code tag_invoke(deserialize_tag, SIMDJSON_IMPLEMENTATION::ondemand::document_reference &doc, T &out)
noexcept(
false) {
301 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
302 SIMDJSON_TRY(doc.get_object().get(obj));
303 return simdjson::deserialize(obj, out);
317template <concepts::smart_po
inter T,
typename ValT>
318error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(
false) {
319 using element_type =
typename std::remove_cvref_t<T>::element_type;
324 deserializable<element_type, ValT>,
325 "The specified type inside the unique_ptr must itself be deserializable");
327 std::is_default_constructible_v<element_type>,
328 "The specified type inside the unique_ptr must default constructible.");
331 std::unique_ptr<element_type> ptr(
new (std::nothrow)
element_type());
335 SIMDJSON_TRY(val.template get<element_type>(*ptr));
336 out = std::move(ptr);
343template <concepts::optional_type T>
344error_code tag_invoke(deserialize_tag,
auto &val, T &out)
noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::value_type,
decltype(val)>) {
345 using value_type =
typename std::remove_cvref_t<T>::value_type;
349 SIMDJSON_TRY( val.is_null().get(is_null_value) );
358 SIMDJSON_TRY(val.template get<value_type>(out.value()));
363#if SIMDJSON_STATIC_REFLECTION
367constexpr bool user_defined_type = (std::is_class_v<T>
368&& !std::is_same_v<T, std::string> && !std::is_same_v<T, std::string_view>
369#if SIMDJSON_SUPPORTS_CHAR8_T
374&& !std::is_same_v<T, std::u8string> && !std::is_same_v<T, std::u8string_view>
376&& !concepts::optional_type<T> &&
377!concepts::appendable_containers<T>
381&& !is_builtin_deserializable_v<T>
382&& !std::is_same_v<T, SIMDJSON_IMPLEMENTATION::ondemand::number>
383&& !std::is_same_v<T, SIMDJSON_IMPLEMENTATION::ondemand::document>
384&& !std::is_same_v<T, SIMDJSON_IMPLEMENTATION::ondemand::document_reference>);
395namespace key_selector_reflection_detail {
399consteval bool is_eligible_member(std::meta::info mem) {
400 return !std::meta::is_const(mem) && std::meta::is_public(mem)
401 && !simdjson::detail::has_annotation(mem, ^^simdjson::detail::skip_tag)
402 && !simdjson::detail::has_annotation(mem, ^^simdjson::detail::skip_deserializing_tag);
409template <std::meta::info First, std::meta::info... Rest>
412 static constexpr std::meta::info leaf = [] {
413 std::meta::info members[] = {First, Rest...};
414 return members[
sizeof...(Rest)];
416 template <
typename T>
417 static simdjson_inline
constexpr auto &get(T &obj)
noexcept {
418 if constexpr (
sizeof...(Rest) == 0) {
419 return obj.[:First:];
421 return member_path<Rest...>::get(obj.[:First:]);
429constexpr bool flattenable_type = user_defined_type<T> && !concepts::string_view_keyed_map<T>
430 && !concepts::container_but_not_string<T> && !concepts::smart_pointer<T>;
432consteval void append_eligible_fields(std::meta::info type, std::vector<std::meta::info> &prefix,
433 std::vector<std::meta::info> &fields) {
434 for (std::meta::info mem : std::meta::nonstatic_data_members_of(type, std::meta::access_context::unchecked())) {
435 if (!is_eligible_member(mem)) {
continue; }
436 prefix.push_back(std::meta::reflect_constant(mem));
437 if (simdjson::detail::has_annotation(mem, ^^simdjson::detail::flatten_tag)) {
438 std::meta::info flattened = simdjson::detail::flattened_type(mem);
439 if (!std::meta::extract<bool>(std::meta::substitute(^^flattenable_type, {flattened}))) {
440 throw std::meta::exception(u8
"simdjson::flatten requires a member whose type is a structure deserialized member by member", mem);
442 append_eligible_fields(flattened, prefix, fields);
444 fields.push_back(std::meta::substitute(^^member_path, prefix));
453consteval std::vector<std::meta::info> eligible_fields(std::meta::info type) {
454 std::vector<std::meta::info> prefix;
455 std::vector<std::meta::info> fields;
456 append_eligible_fields(type, prefix, fields);
461consteval std::meta::info field_leaf(std::meta::info path) {
462 return std::meta::extract<std::meta::info>(std::meta::template_arguments_of(path).back());
470consteval std::size_t eligible_field_count() {
471 return eligible_fields(^^T).size();
476consteval std::vector<const char *> accepted_keys_of(std::meta::info entity) {
477 std::vector<const char *> keys;
478 for (std::string_view key :
simdjson::detail::json_key_names(entity)) {
479 bool repeated =
false;
480 for (
const char *previous : keys) { repeated = repeated || std::string_view(previous) == key; }
481 if (!repeated) { keys.push_back(std::define_static_string(key)); }
488consteval std::vector<const char *> accepted_keys(std::meta::info type) {
489 std::vector<const char *> keys;
490 for (std::meta::info path : eligible_fields(type)) {
491 for (
const char *key : accepted_keys_of(field_leaf(path))) { keys.push_back(key); }
497consteval std::vector<std::size_t> accepted_key_fields(std::meta::info type) {
498 std::vector<std::size_t> key_fields;
499 std::vector<std::meta::info> fields = eligible_fields(type);
500 for (std::size_t i = 0; i < fields.size(); ++i) {
501 for (std::size_t j = 0; j < accepted_keys_of(field_leaf(fields[i])).size(); ++j) { key_fields.push_back(i); }
509consteval bool accepted_keys_are_distinct() {
510 std::vector<const char *> keys = accepted_keys(^^T);
511 for (std::size_t i = 0; i < keys.size(); ++i) {
512 for (std::size_t j = i + 1; j < keys.size(); ++j) {
513 if (std::string_view(keys[i]) == std::string_view(keys[j])) {
return false; }
524consteval bool keys_need_unescaping() {
525 for (std::string_view key : accepted_keys(^^T)) {
527 if (c ==
'\\' || c ==
'"' ||
static_cast<unsigned char>(c) < 0x20) {
return true; }
536consteval bool has_aliases() {
537 return accepted_keys(^^T).size() != eligible_fields(^^T).size();
543consteval bool has_default() {
544 return simdjson::detail::has_annotation(mem, ^^simdjson::detail::default_value_tag)
545 || simdjson::detail::has_annotation(std::meta::parent_of(mem), ^^simdjson::detail::default_value_tag)
546 || simdjson::detail::annotation_of_template(mem, ^^simdjson::detail::default_from_t) != std::meta::info{};
552consteval bool may_be_absent() {
553 return concepts::optional_type<
typename [: std::meta::type_of(mem) :]> || has_default<mem>();
560consteval bool all_eligible_fields_required() {
561 bool all_required =
true;
562 template for (
constexpr auto path : std::define_static_array(eligible_fields(^^T))) {
563 if constexpr (may_be_absent<[: path :]::leaf>()) {
564 all_required =
false;
571template <const
char *key>
572consteval auto key_fixed_string() {
573 constexpr std::string_view key_view{ key };
574 char buffer[key_view.size() + 1] = {};
575 for (std::size_t i = 0; i < key_view.size(); ++i) { buffer[i] = key_view[i]; }
576 return constevalutil::fixed_string<key_view.size() + 1>(buffer);
582consteval std::vector<std::meta::info> selector_key_args() {
583 std::vector<std::meta::info> args;
584 template for (
constexpr const char *key : std::define_static_array(accepted_keys(^^T))) {
585 args.push_back(std::meta::reflect_constant(key_fixed_string<key>()));
592using selector_for =
typename [: std::meta::substitute(
593 ^^SIMDJSON_IMPLEMENTATION::ondemand::key_selector, selector_key_args<T>()) :];
604consteval bool keys_fit_selector() {
605 std::vector<std::string_view> keys;
606 for (
const char *key : accepted_keys(^^T)) { keys.push_back(key); }
607 if (keys.size() > 255) {
return false; }
608 for (std::size_t i = 0; i < keys.size(); ++i) {
609 if (keys[i].empty() || keys[i].size() > 63) {
return false; }
610 for (
char c : keys[i]) {
611 if (c ==
'\\' || c ==
'"' ||
static_cast<unsigned char>(c) < 0x20) {
return false; }
613 for (std::size_t j = i + 1; j < keys.size(); ++j) {
614 if (keys[i] == keys[j]) {
return false; }
621consteval bool declares_deserialize(std::meta::info adapter) {
622 for (std::meta::info m : std::meta::members_of(adapter, std::meta::access_context::unchecked())) {
623 if (std::meta::has_identifier(m) && std::meta::identifier_of(m) ==
"deserialize") {
return true; }
631template <auto mem,
typename ValueT,
typename M>
632simdjson_warn_unused simdjson_inline
error_code deserialize_member_value(ValueT &field_value, M &target)
noexcept(
false) {
633 constexpr std::meta::info with_type = simdjson::detail::annotation_of_template(mem, ^^simdjson::detail::with_t);
634 if constexpr (with_type != std::meta::info{}) {
635 using adapter =
typename [: with_type :]::adapter;
636 using ondemand_value = SIMDJSON_IMPLEMENTATION::ondemand::value;
637 if constexpr (
requires { { adapter::deserialize(field_value, target) } -> std::convertible_to<error_code>; }) {
638 return adapter::deserialize(field_value, target);
639 }
else if constexpr (
requires(ondemand_value &v) { { adapter::deserialize(v, target) } -> std::convertible_to<error_code>; }
640 &&
requires { field_value.get_value(); }) {
646 SIMDJSON_TRY(field_value.get_value().get(v));
647 return adapter::deserialize(v, target);
649 static_assert(!declares_deserialize(^^adapter),
650 "the deserialize function of a simdjson::with adapter must be callable as "
651 "Adapter::deserialize(simdjson::ondemand::value &, T &) and return an error_code");
652 return field_value.get(target);
655 return field_value.get(target);
660template <auto mem,
typename ValueT,
typename M>
661simdjson_warn_unused simdjson_inline
error_code deserialize_member(ValueT &field_value, M &target)
noexcept(
false) {
662 if constexpr (has_default<mem>() && std::is_default_constructible_v<M> && std::is_move_assignable_v<M>) {
667 SIMDJSON_TRY(deserialize_member_value<mem>(field_value, value));
668 target = std::move(value);
671 return deserialize_member_value<mem>(field_value, target);
677simdjson_warn_unused simdjson_inline
error_code deserialize_field_at(
678 std::size_t field_index, SIMDJSON_IMPLEMENTATION::ondemand::value field_value, T &out)
noexcept(
false) {
679 std::size_t counter = 0;
680 template for (
constexpr auto path : std::define_static_array(eligible_fields(^^T))) {
681 using field = [: path :];
682 if (field_index == counter) {
return deserialize_member<field::leaf>(field_value, field::get(out)); }
691template <auto mem,
typename M>
692simdjson_warn_unused simdjson_inline
error_code on_missing_member(M &target)
noexcept(
false) {
693 constexpr std::meta::info default_from_type = simdjson::detail::annotation_of_template(mem, ^^simdjson::detail::default_from_t);
694 if constexpr (default_from_type != std::meta::info{}) {
695 target = [: default_from_type :]::factory();
697 }
else if constexpr (may_be_absent<mem>()) {
709template <
typename T, std::
size_t N>
710simdjson_warn_unused simdjson_inline
error_code handle_missing_fields(
711 const std::array<bool, N> &seen_field, T &out)
noexcept(
false) {
712 std::size_t counter = 0;
713 template for (
constexpr auto path : std::define_static_array(eligible_fields(^^T))) {
714 using field = [: path :];
715 if (!seen_field[counter]) { SIMDJSON_TRY(on_missing_member<field::leaf>(field::get(out))); }
726simdjson_warn_unused
error_code deserialize_struct_ordered(
727 SIMDJSON_IMPLEMENTATION::ondemand::object &obj, T &out)
noexcept(
false) {
728 template for (
constexpr auto path : std::define_static_array(eligible_fields(^^T))) {
729 using field = [: path :];
730 SIMDJSON_IMPLEMENTATION::ondemand::value field_value;
732 template for (
constexpr const char *key : std::define_static_array(accepted_keys_of(field::leaf))) {
733 if (error == NO_SUCH_FIELD) { error = obj[std::string_view(key)].get(field_value); }
735 if (error == NO_SUCH_FIELD) {
736 SIMDJSON_TRY(on_missing_member<field::leaf>(field::get(out)));
740 SIMDJSON_TRY(deserialize_member<field::leaf>(field_value, field::get(out)));
751consteval void append_unassignable_keys(std::meta::info type,
bool all, std::vector<const char *> &keys) {
752 for (std::meta::info mem : std::meta::nonstatic_data_members_of(type, std::meta::access_context::unchecked())) {
753 if (simdjson::detail::has_annotation(mem, ^^simdjson::detail::skip_tag)
754 || simdjson::detail::has_annotation(mem, ^^simdjson::detail::skip_serializing_tag)
755 || simdjson::detail::has_annotation(mem, ^^simdjson::detail::skip_deserializing_tag)) {
758 bool unassignable = all || !is_eligible_member(mem);
759 if (simdjson::detail::has_annotation(mem, ^^simdjson::detail::flatten_tag)) {
760 append_unassignable_keys(simdjson::detail::flattened_type(mem), unassignable, keys);
761 }
else if (unassignable) {
762 keys.push_back(std::define_static_string(simdjson::detail::json_key_name(mem)));
767consteval std::vector<const char *> unassignable_keys(std::meta::info type) {
768 std::vector<const char *> keys;
769 append_unassignable_keys(type,
false, keys);
780template <
bool DenyUnknown,
typename T>
781simdjson_warn_unused
error_code deserialize_struct_scan(
782 SIMDJSON_IMPLEMENTATION::ondemand::object &obj, T &out)
noexcept(
false) {
783 static constexpr auto keys = std::define_static_array(accepted_keys(^^T));
784 static constexpr auto key_fields = std::define_static_array(accepted_key_fields(^^T));
785 std::array<bool, eligible_field_count<T>()> seen_field{};
786 for (
auto field_result : obj) {
787 SIMDJSON_IMPLEMENTATION::ondemand::field json_field;
788 SIMDJSON_TRY(std::move(field_result).get(json_field));
789 std::string_view key;
790 SIMDJSON_TRY(json_field.unescaped_key().get(key));
791 std::size_t key_index = keys.size();
792 for (std::size_t i = 0; i < keys.size(); ++i) {
793 if (key == std::string_view(keys[i])) { key_index = i;
break; }
795 if (key_index == keys.size()) {
796 if constexpr (DenyUnknown) {
799 static constexpr auto ignored_keys = std::define_static_array(unassignable_keys(^^T));
800 bool ignored =
false;
801 for (
const char *ignored_key : ignored_keys) {
802 if (key == std::string_view(ignored_key)) { ignored =
true;
break; }
808 const std::size_t field_index = key_fields[key_index];
809 if (seen_field[field_index]) {
continue; }
810 seen_field[field_index] =
true;
811 SIMDJSON_TRY(deserialize_field_at(field_index, json_field.value(), out));
813 return handle_missing_fields(seen_field, out);
817consteval bool is_transparent() {
818 return simdjson::detail::has_annotation(^^T, ^^simdjson::detail::transparent_tag);
839template <
typename T,
typename ValT>
840 requires(user_defined_type<T> && std::is_class_v<T>)
841error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept(
false) {
842 if constexpr (key_selector_reflection_detail::is_transparent<T>()) {
843 constexpr auto mem = simdjson::detail::transparent_member(^^T);
844 if constexpr (std::is_same_v<std::remove_cvref_t<ValT>, SIMDJSON_IMPLEMENTATION::ondemand::object>) {
846 if constexpr (user_defined_type<
typename [: std::meta::type_of(mem) :]>) {
847 return tag_invoke(deserialize_tag{}, val, out.[:mem:]);
852 return key_selector_reflection_detail::deserialize_member<mem>(val, out.[:mem:]);
855 static_assert(key_selector_reflection_detail::accepted_keys_are_distinct<T>(),
856 "two members of this structure accept the same JSON key (check rename, alias, "
857 "rename_all and flatten)");
858 SIMDJSON_IMPLEMENTATION::ondemand::object obj;
859 if constexpr (std::is_same_v<std::remove_cvref_t<ValT>, SIMDJSON_IMPLEMENTATION::ondemand::object>) {
862 SIMDJSON_TRY(val.get_object().get(obj));
864 if constexpr (simdjson::detail::has_annotation(^^T, ^^simdjson::detail::deny_unknown_fields_tag)) {
865 return key_selector_reflection_detail::deserialize_struct_scan<true>(obj, out);
867#if defined(SIMDJSON_DISABLE_KEY_SELECTOR_REFLECTION) && SIMDJSON_DISABLE_KEY_SELECTOR_REFLECTION
870 if constexpr (key_selector_reflection_detail::keys_need_unescaping<T>()) {
871 return key_selector_reflection_detail::deserialize_struct_scan<false>(obj, out);
873 return key_selector_reflection_detail::deserialize_struct_ordered(obj, out);
876 if constexpr (key_selector_reflection_detail::eligible_field_count<T>() == 0) {
883 }
else if constexpr (!key_selector_reflection_detail::keys_fit_selector<T>()) {
889 return key_selector_reflection_detail::deserialize_struct_scan<false>(obj, out);
891 using selector = key_selector_reflection_detail::selector_for<T>;
892 if constexpr (key_selector_reflection_detail::all_eligible_fields_required<T>()
893 && !key_selector_reflection_detail::has_aliases<T>()) {
899 auto walk = obj.template for_each<selector>(
900 [&](std::size_t matched_index, SIMDJSON_IMPLEMENTATION::ondemand::value field_value) ->
error_code {
901 std::size_t counter = 0;
902 template for (
constexpr auto path : std::define_static_array(key_selector_reflection_detail::eligible_fields(^^T))) {
903 using field = [: path :];
904 if (matched_index == counter) {
return key_selector_reflection_detail::deserialize_member<field::leaf>(field_value, field::get(out)); }
909 if (walk.error) {
return walk.error; }
912 if (walk.matched_count != selector::size()) {
return NO_SUCH_FIELD; }
915 static constexpr auto key_fields = std::define_static_array(key_selector_reflection_detail::accepted_key_fields(^^T));
916 std::array<bool, key_selector_reflection_detail::eligible_field_count<T>()> seen_field{};
922 error_code walk_error = obj.template for_each<selector>(
923 [&](std::size_t matched_index, SIMDJSON_IMPLEMENTATION::ondemand::value field_value) ->
error_code {
924 const std::size_t field_index = key_fields[matched_index];
925 if (seen_field[field_index]) {
return SUCCESS; }
926 seen_field[field_index] =
true;
927 return key_selector_reflection_detail::deserialize_field_at(field_index, field_value, out);
929 if (walk_error) {
return walk_error; }
933 return key_selector_reflection_detail::handle_missing_fields(seen_field, out);
944template <
typename T,
typename ValT>
945 requires(std::is_enum_v<T>)
946error_code tag_invoke(deserialize_tag, ValT &val, T &out)
noexcept {
947#if SIMDJSON_STATIC_REFLECTION
948 std::string_view str;
949 SIMDJSON_TRY(val.get_string().get(str));
950 static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
951 template for (
constexpr auto enum_val : enumerators) {
952 template for (
constexpr const char *key : std::define_static_array(key_selector_reflection_detail::accepted_keys_of(enum_val))) {
953 if (str == std::string_view(key)) {
963 std::underlying_type_t<T> int_val;
964 SIMDJSON_TRY(val.get(int_val));
965 out =
static_cast<T
>(int_val);
970template <
typename simdjson_value,
typename T>
971 requires(user_defined_type<std::remove_cvref_t<T>>)
972error_code tag_invoke(deserialize_tag, simdjson_value &val, std::unique_ptr<T> &out)
noexcept(
false) {
973 std::unique_ptr<T> ptr(
new (std::nothrow) T());
977 SIMDJSON_TRY(val.get(*ptr));
978 out = std::move(ptr);
982template <
typename simdjson_value,
typename T>
983 requires(user_defined_type<std::remove_cvref_t<T>>)
984error_code tag_invoke(deserialize_tag, simdjson_value &val, std::shared_ptr<T> &out)
noexcept(
false) {
985 std::shared_ptr<T> ptr(
new (std::nothrow) T());
989 SIMDJSON_TRY(val.get(*ptr));
990 out = std::move(ptr);
999error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<bool> &out)
noexcept {
1001 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1002 if (is_null_value) {
1007 out = std::make_unique<bool>();
1010 SIMDJSON_TRY(val.get_bool().get(*out));
1014error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<int64_t> &out)
noexcept {
1016 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1017 if (is_null_value) {
1022 out = std::make_unique<int64_t>();
1025 SIMDJSON_TRY(val.get_int64().get(*out));
1029error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<uint64_t> &out)
noexcept {
1031 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1032 if (is_null_value) {
1037 out = std::make_unique<uint64_t>();
1040 SIMDJSON_TRY(val.get_uint64().get(*out));
1044error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<double> &out)
noexcept {
1046 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1047 if (is_null_value) {
1052 out = std::make_unique<double>();
1055 SIMDJSON_TRY(val.get_double().get(*out));
1059error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<std::string_view> &out)
noexcept {
1061 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1062 if (is_null_value) {
1067 out = std::make_unique<std::string_view>();
1070 SIMDJSON_TRY(val.get_string().get(*out));
1078error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<bool> &out)
noexcept {
1080 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1081 if (is_null_value) {
1086 out = std::make_shared<bool>();
1089 SIMDJSON_TRY(val.get_bool().get(*out));
1093error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<int64_t> &out)
noexcept {
1095 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1096 if (is_null_value) {
1101 out = std::make_shared<int64_t>();
1104 SIMDJSON_TRY(val.get_int64().get(*out));
1108error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<uint64_t> &out)
noexcept {
1110 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1111 if (is_null_value) {
1116 out = std::make_shared<uint64_t>();
1119 SIMDJSON_TRY(val.get_uint64().get(*out));
1123error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<double> &out)
noexcept {
1125 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1126 if (is_null_value) {
1131 out = std::make_shared<double>();
1134 SIMDJSON_TRY(val.get_double().get(*out));
1138error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<std::string_view> &out)
noexcept {
1140 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1141 if (is_null_value) {
1146 out = std::make_shared<std::string_view>();
1149 SIMDJSON_TRY(val.get_string().get(*out));
1161error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<std::string> &out)
noexcept {
1164 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1165 if (is_null_value) {
1171 out = std::make_unique<std::string>();
1173 std::string_view str;
1174 SIMDJSON_TRY(val.get_string().get(str));
1175 *out = std::string{str};
1179error_code tag_invoke(deserialize_tag,
auto &val, std::shared_ptr<std::string> &out)
noexcept {
1182 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1183 if (is_null_value) {
1189 out = std::make_shared<std::string>();
1191 std::string_view str;
1192 SIMDJSON_TRY(val.get_string().get(str));
1193 *out = std::string{str};
1197error_code tag_invoke(deserialize_tag,
auto &val, std::unique_ptr<int> &out)
noexcept {
1200 SIMDJSON_TRY( val.is_null().get(is_null_value) );
1201 if (is_null_value) {
1207 out = std::make_unique<int>();
1210 SIMDJSON_TRY(val.get_int64().get(temp));
1211 *out =
static_cast<int>(temp);
Provides compile-time annotations for simdjson structures.
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.
@ UNKNOWN_FIELD
JSON field does not map to any member of the target (see simdjson::deny_unknown_fields)
@ NUMBER_OUT_OF_RANGE
JSON number does not fit in 64 bits.
@ MEMALLOC
Error allocating memory, most likely out of memory.