simdjson  3.11.0
Ridiculously Fast JSON
std_deserialize.h
1 #if SIMDJSON_SUPPORTS_DESERIALIZATION
2 
3 #ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H
4 #ifndef SIMDJSON_CONDITIONAL_INCLUDE
5 #define SIMDJSON_ONDEMAND_DESERIALIZE_H
6 #include "simdjson/generic/ondemand/array.h"
7 #include "simdjson/generic/ondemand/base.h"
8 #endif // SIMDJSON_CONDITIONAL_INCLUDE
9 
10 #include <concepts>
11 #include <limits>
12 
13 namespace simdjson {
14 template <typename T>
15 constexpr bool require_custom_serialization = false;
16 
18 // Number deserialization
20 
21 template <std::unsigned_integral T>
22  requires(!require_custom_serialization<T>)
23 error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept {
24  using limits = std::numeric_limits<T>;
25 
26  uint64_t x;
27  SIMDJSON_TRY(val.get_uint64().get(x));
28  if (x > (limits::max)()) {
29  return NUMBER_OUT_OF_RANGE;
30  }
31  out = static_cast<T>(x);
32  return SUCCESS;
33 }
34 
35 template <std::floating_point T>
36  requires(!require_custom_serialization<T>)
37 error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept {
38  double x;
39  SIMDJSON_TRY(val.get_double().get(x));
40  out = static_cast<T>(x);
41  return SUCCESS;
42 }
43 
44 template <std::signed_integral T>
45  requires(!require_custom_serialization<T>)
46 error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept {
47  using limits = std::numeric_limits<T>;
48 
49  int64_t x;
50  SIMDJSON_TRY(val.get_int64().get(x));
51  if (x > (limits::max)() || x < (limits::min)()) {
52  return NUMBER_OUT_OF_RANGE;
53  }
54  out = static_cast<T>(x);
55  return SUCCESS;
56 }
57 
65 template <concepts::appendable_containers T, typename ValT>
66  requires(!require_custom_serialization<T>)
67 error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) {
68  using value_type = typename std::remove_cvref_t<T>::value_type;
69  static_assert(
70  deserializable<value_type, ValT>,
71  "The specified type inside the container must itself be deserializable");
72  static_assert(
73  std::is_default_constructible_v<value_type>,
74  "The specified type inside the container must default constructible.");
75 
76  SIMDJSON_IMPLEMENTATION::ondemand::array arr;
77  SIMDJSON_TRY(val.get_array().get(arr));
78  for (auto v : arr) {
79  if constexpr (concepts::returns_reference<T>) {
80  if (auto const err = v.get<value_type>().get(concepts::emplace_one(out));
81  err) {
82  // If an error occurs, the empty element that we just inserted gets
83  // removed. We're not using a temp variable because if T is a heavy
84  // type, we want the valid path to be the fast path and the slow path be
85  // the path that has errors in it.
86  if constexpr (requires { out.pop_back(); }) {
87  static_cast<void>(out.pop_back());
88  }
89  return err;
90  }
91  } else {
92  value_type temp;
93  if (auto const err = v.get<value_type>().get(temp); err) {
94  return err;
95  }
96  concepts::emplace_one(out, std::move(temp));
97  }
98  }
99  return SUCCESS;
100 }
101 
102 
103 
118 template <concepts::smart_pointer T, typename ValT>
119  requires(!require_custom_serialization<T>)
120 error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::element_type, ValT>) {
121  using element_type = typename std::remove_cvref_t<T>::element_type;
122 
123  // For better error messages, don't use these as constraints on
124  // the tag_invoke CPO.
125  static_assert(
126  deserializable<element_type, ValT>,
127  "The specified type inside the unique_ptr must itself be deserializable");
128  static_assert(
129  std::is_default_constructible_v<element_type>,
130  "The specified type inside the unique_ptr must default constructible.");
131 
132  auto ptr = new (std::nothrow) element_type();
133  if (ptr == nullptr) {
134  return MEMALLOC;
135  }
136  SIMDJSON_TRY(val.template get<element_type>(*ptr));
137  out.reset(ptr);
138  return SUCCESS;
139 }
140 
144 template <concepts::optional_type T, typename ValT>
145  requires(!require_custom_serialization<T>)
146 error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::value_type, ValT>) {
147  using value_type = typename std::remove_cvref_t<T>::value_type;
148 
149  static_assert(
150  deserializable<value_type, ValT>,
151  "The specified type inside the unique_ptr must itself be deserializable");
152  static_assert(
153  std::is_default_constructible_v<value_type>,
154  "The specified type inside the unique_ptr must default constructible.");
155 
156  if (!out) {
157  out.emplace();
158  }
159  SIMDJSON_TRY(val.template get<value_type>(out.value()));
160  return SUCCESS;
161 }
162 
163 } // namespace simdjson
164 
165 #endif // SIMDJSON_ONDEMAND_DESERIALIZE_H
166 #endif // SIMDJSON_SUPPORTS_DESERIALIZATION
element_type
The actual concrete type of a JSON element This is the type it is most easily cast to with get<>.
Definition: element.h:14
The top level simdjson namespace, containing everything the library provides.
Definition: base.h:8
error_code
All possible errors returned by simdjson.
Definition: error.h:19
@ NUMBER_OUT_OF_RANGE
JSON number does not fit in 64 bits.
Definition: error.h:38
@ MEMALLOC
Error allocating memory, most likely out of memory.
Definition: error.h:22
@ SUCCESS
No error.
Definition: error.h:20