52 namespace json_details {
55 number_parse_type_impl_test( ) {
56 if constexpr( daw::is_floating_point_v<T> ) {
57 return JsonParseTypes::Real;
58 }
else if constexpr( daw::is_signed_v<T> ) {
59 return JsonParseTypes::Signed;
61 static_assert( daw::is_unsigned_v<T> );
62 return JsonParseTypes::Unsigned;
67 DAW_ATTRIB_INLINE DAW_CONSTEVAL
JsonParseTypes number_parse_type_test( ) {
68 if constexpr( std::is_enum_v<T> ) {
69 return number_parse_type_impl_test<std::underlying_type_t<T>>( );
71 return number_parse_type_impl_test<T>( );
77 number_parse_type_test<T>( );
79 template<
typename,
typename =
void>
80 struct json_deduced_type_map {
81 static constexpr bool is_null =
false;
82 static constexpr auto parse_type = JsonParseTypes::Unknown;
84 static constexpr bool type_map_found =
false;
87 template<
typename JsonType>
89 struct json_deduced_type_map<
90 JsonType DAW_ENABLEIF_S( is_a_json_type_v<JsonType> )> {
91 static constexpr bool is_null =
false;
92 static constexpr auto parse_type = JsonParseTypes::Unknown;
94 using type = JsonType;
95 static constexpr bool type_map_found =
true;
100 struct json_deduced_type_map<
101 T DAW_ENABLEIF_S( has_json_data_contract_trait_v<T> )> {
102 static constexpr bool is_null =
false;
104 static_assert( is_json_member_list_v<type>,
105 "Expected a JSON member list" );
106 static constexpr auto parse_type = JsonParseTypes::Unknown;
108 static constexpr bool type_map_found =
true;
112 struct json_deduced_type_map<
daw::string_view> {
113 static constexpr bool is_null =
false;
114 static constexpr auto parse_type = JsonParseTypes::StringRaw;
116 static constexpr bool type_map_found =
true;
120 struct json_deduced_type_map<
std::string_view> {
121 static constexpr bool is_null =
false;
122 static constexpr auto parse_type = JsonParseTypes::StringRaw;
124 static constexpr bool type_map_found =
true;
128 struct json_deduced_type_map<
std::string> {
129 static constexpr bool is_null =
false;
130 static constexpr auto parse_type = JsonParseTypes::StringEscaped;
132 static constexpr bool type_map_found =
true;
136 struct json_deduced_type_map<bool> {
137 static constexpr bool is_null =
false;
138 static constexpr auto parse_type = JsonParseTypes::Bool;
139 static constexpr bool type_map_found =
true;
144#if defined( _LIBCPP_VERSION )
146 struct json_deduced_type_map<
147 typename
std::vector<bool>::const_reference> {
149 static constexpr bool is_null =
false;
150 static constexpr auto parse_type = JsonParseTypes::Bool;
152 static constexpr bool type_map_found =
true;
156 template<
typename Integer>
158 not json_details::has_json_data_contract_trait_v<Integer> and
159 daw::is_integral_v<Integer> )
160 struct json_deduced_type_map<Integer DAW_ENABLEIF_S(
161 not json_details::has_json_data_contract_trait_v<Integer> and
162 daw::is_integral_v<Integer> )> {
163 static constexpr bool is_null =
false;
164 static constexpr auto parse_type = daw::is_signed_v<Integer>
165 ? JsonParseTypes::Signed
166 : JsonParseTypes::Unsigned;
168 static constexpr bool type_map_found =
true;
171 template<
typename Enum>
172 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Enum> and
173 std::is_enum_v<Enum> )
174 struct json_deduced_type_map<Enum DAW_ENABLEIF_S(
175 not json_details::has_json_data_contract_trait_v<Enum> and
176 std::is_enum_v<Enum> )> {
177 static constexpr bool is_null =
false;
178 static constexpr auto parse_type =
179 daw::is_signed_v<std::underlying_type<Enum>>
180 ? JsonParseTypes::Signed
181 : JsonParseTypes::Unsigned;
183 static constexpr bool type_map_found =
true;
186 template<
typename FloatingPo
int>
188 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
189 daw::is_floating_point_v<FloatingPoint> )
190 struct json_deduced_type_map<FloatingPoint DAW_ENABLEIF_S(
191 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
192 daw::is_floating_point_v<FloatingPoint> )> {
193 static constexpr bool is_null =
false;
194 static constexpr auto parse_type = JsonParseTypes::Real;
196 static constexpr bool type_map_found =
true;
199 template<
typename Tuple>
200 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Tuple> and
202 struct json_deduced_type_map<Tuple DAW_ENABLEIF_S(
203 not json_details::has_json_data_contract_trait_v<Tuple> and
204 is_tuple_v<Tuple> )> {
205 static constexpr bool is_null =
false;
206 static constexpr auto parse_type = JsonParseTypes::Tuple;
208 static constexpr bool type_map_found =
true;
211 namespace container_detect {
213 using is_string_test =
214 decltype( (void)( std::begin( std::declval<T &>( ) ) ),
215 (
void)( std::end( std::declval<T &>( ) ) ),
216 std::declval<typename T::value_type>( ) );
219 template<
typename String>
220 DAW_CPP20_CONCEPT is_string_v = std::is_convertible_v<
221 char, daw::detected_t<container_detect::is_string_test, String>>;
224 is_associative_container_v,
225 ( (
void)( std::begin( std::declval<T &>( ) ) ),
226 (
void)( std::end( std::declval<T &>( ) ) ),
227 (
void)( std::declval<typename T::value_type>( ) ),
228 (
void)( std::declval<typename T::key_type>( ) ),
229 (
void)( std::declval<typename T::mapped_type>( ) ) ) );
231 template<
typename AssociativeContainer>
232 DAW_REQUIRES( not has_json_data_contract_trait_v<AssociativeContainer> and
233 is_associative_container_v<AssociativeContainer> )
234 struct json_deduced_type_map<AssociativeContainer DAW_ENABLEIF_S(
235 not has_json_data_contract_trait_v<AssociativeContainer> and
236 is_associative_container_v<AssociativeContainer> )> {
237 static constexpr bool is_null =
false;
238 using key =
typename AssociativeContainer::key_type;
239 using value =
typename AssociativeContainer::mapped_type;
240 static constexpr auto parse_type = JsonParseTypes::KeyValue;
242 static constexpr bool type_map_found =
true;
246 DAW_CPP20_CONCEPT is_deduced_array_v =
247 not has_json_data_contract_trait_v<T> and
248 not is_associative_container_v<T> and concepts::is_container_v<T> and
251 template<
typename Container>
253 struct json_deduced_type_map<
254 Container DAW_ENABLEIF_S( is_deduced_array_v<Container> )> {
255 static constexpr bool is_null =
false;
256 using value =
typename Container::value_type;
257 static constexpr auto parse_type = JsonParseTypes::Array;
259 static constexpr bool type_map_found =
true;
263 DAW_CPP20_CONCEPT has_nullable_type_map_v =
264 concepts::is_nullable_value_v<T> and
265 not has_json_data_contract_trait_v<T> and
266 daw::is_detected_v<json_deduced_type_map,
267 concepts::nullable_value_type_t<T>>;
271 struct json_deduced_type_map<
272 T DAW_ENABLEIF_S( has_nullable_type_map_v<T> )> {
273 static constexpr bool is_null =
true;
274 using sub_type = concepts::nullable_value_type_t<T>;
275 using type = json_deduced_type_map<sub_type>;
276 static constexpr auto parse_type = type::parse_type;
277 static constexpr bool type_map_found =
true;
281 DAW_CPP20_CONCEPT has_deduced_type_mapping_v =
282 json_deduced_type_map<T>::type_map_found;
284 template<
typename... Ts>
285 DAW_CPP20_CONCEPT are_deduced_type_mapped_v =
286 ( has_deduced_type_mapping_v<Ts> and ... );
288 template<
typename Mapped,
bool Found = true>
289 struct json_link_quick_map_type {
290 static constexpr bool value = Found;
291 using mapped_type = Mapped;
294 template<JsonParseTypes Value>
295 DAW_CPP20_CONCEPT is_arithmetic_parse_type_v =
296 daw::traits::equal_to_any_of_v<Value, JsonParseTypes::Signed,
297 JsonParseTypes::Unsigned,
298 JsonParseTypes::Real>;
301 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_link_quick_map( )
noexcept {
302 if constexpr( is_a_json_type_v<T> ) {
303 return json_link_quick_map_type<T>{ };
304 }
else if constexpr( has_deduced_type_mapping_v<T> ) {
305 using mapped_type_t = json_deduced_type_map<T>;
306 using parse_type = daw::constant<mapped_type_t::parse_type>;
307 using is_null = daw::constant<mapped_type_t::is_null>;
308 if constexpr( parse_type::value == JsonParseTypes::Unknown ) {
309 if constexpr( is_null::value ) {
310 if constexpr( has_json_data_contract_trait_v<
311 typename mapped_type_t::sub_type> ) {
312 return json_link_quick_map_type<
313 json_base::json_class_null<T>>{ };
315 return json_link_quick_map_type<json_base::json_raw_null<T>>{ };
318 return json_link_quick_map_type<json_base::json_raw<T>>{ };
320 }
else if constexpr( parse_type::value ==
321 JsonParseTypes::StringRaw ) {
322 if constexpr( is_null::value ) {
323 return json_link_quick_map_type<
324 json_base::json_string_raw_null<T>>{ };
326 return json_link_quick_map_type<json_base::json_string_raw<T>>{ };
328 }
else if constexpr( parse_type::value ==
329 JsonParseTypes::StringEscaped ) {
330 if constexpr( is_null::value ) {
331 return json_link_quick_map_type<
332 json_base::json_string_null<T>>{ };
334 return json_link_quick_map_type<json_base::json_string<T>>{ };
336 }
else if constexpr( parse_type::value == JsonParseTypes::Bool ) {
337 if constexpr( is_null::value ) {
338 return json_link_quick_map_type<json_base::json_bool_null<T>>{ };
340 return json_link_quick_map_type<json_base::json_bool<T>>{ };
342 }
else if constexpr( is_arithmetic_parse_type_v<parse_type::value> ) {
343 if constexpr( is_null::value ) {
344 return json_link_quick_map_type<
345 json_base::json_number_null<T>>{ };
347 return json_link_quick_map_type<json_base::json_number<T>>{ };
349 }
else if constexpr( parse_type::value == JsonParseTypes::Tuple ) {
350 if constexpr( is_null::value ) {
351 return json_link_quick_map_type<json_base::json_tuple_null<T>>{ };
353 return json_link_quick_map_type<json_base::json_tuple<T>>{ };
355 }
else if constexpr( parse_type::value == JsonParseTypes::KeyValue ) {
356 if constexpr( is_null::value ) {
357 using b_t = json_base_type_t<mapped_type_t>;
358 using k_t =
typename b_t::key;
359 using v_t =
typename b_t::value;
360 return json_link_quick_map_type<
361 json_base::json_key_value_null<T, v_t, k_t>>{ };
363 using k_t =
typename mapped_type_t::key;
364 using v_t =
typename mapped_type_t::value;
365 return json_link_quick_map_type<
366 json_base::json_key_value<T, v_t, k_t>>{ };
368 }
else if constexpr( parse_type::value == JsonParseTypes::Array ) {
369 if constexpr( is_null::value ) {
370 using b_t = json_base_type_t<mapped_type_t>;
371 using v_t =
typename b_t::value;
372 return json_link_quick_map_type<
373 json_base::json_nullable<T, json_base::json_array<v_t, T>>>{ };
375 using v_t =
typename mapped_type_t::value;
376 return json_link_quick_map_type<json_base::json_array<v_t, T>>{ };
378#if defined( DAW_JSON_HAS_REFLECTION )
379 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
380 return json_link_quick_map_type<
381 json_base::json_reflected_class<T>>{ };
384 return json_link_quick_map_type<void, false>{ };
386#if defined( DAW_JSON_HAS_REFLECTION )
387 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
388 return json_link_quick_map_type<
389 json_base::json_reflected_class<T>>{ };
392 return json_link_quick_map_type<void, false>{ };
398 DAW_CPP20_CONCEPT has_json_link_quick_map_v =
399 decltype( json_link_quick_map<T>( ) )::value;
403 using json_link_quick_map_t =
404 typename decltype( json_link_quick_map<T>( ) )::mapped_type;
406 template<
typename JsonType>
407 struct json_class_map_type {
412 struct is_json_class_map : std::false_type {};
416 inline constexpr bool is_json_class_map_v =
417 has_json_data_contract_trait_v<T> and
418 is_json_class_map_v<json_data_contract_trait_t<T>>;
421 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_deduced_type_impl( )
noexcept {
422 if constexpr( is_a_basic_json_value<T> ) {
423 return daw::traits::identity<json_base::json_raw<T>>{ };
424 }
else if constexpr( is_an_ordered_member_v<T> ) {
426 return daw::traits::identity<type>{ };
427 }
else if constexpr( has_json_data_contract_trait_v<T> ) {
428 static_assert( not std::is_same_v<T, void> );
430 using type = json_base::json_class<T>;
432 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
433 "Detection failure" );
434 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
435 "Detection failure" );
436 return daw::traits::identity<type>{ };
437 }
else if constexpr( has_json_link_quick_map_v<T> ) {
438 static_assert( not std::is_same_v<T, void> );
439 using type = json_link_quick_map_t<T>;
440 using rcvref_type = remove_cvref_t<type>;
441 static_assert( not std::is_same_v<rcvref_type, void>,
442 "Detection failure" );
443 static_assert( not is_nonesuch_v<rcvref_type>,
"Detection failure" );
444 return daw::traits::identity<type>{ };
445 }
else if constexpr( is_a_json_type_v<T> ) {
446 static_assert( not std::is_same_v<T, void> );
448 typename daw::conditional_t<is_json_class_map_v<T>,
449 json_class_map_type<T>,
450 daw::traits::identity<T>>::type;
451 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
452 "Detection failure" );
453 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
454 "Detection failure" );
455 return daw::traits::identity<type>{ };
456 }
else if constexpr( concepts::is_nullable_value_v<T> ) {
457 using value_type = concepts::nullable_value_type_t<T>;
459 typename decltype( json_deduced_type_impl<value_type>( ) )::type;
460 using type = json_base::json_nullable<T, sub_type>;
461 return daw::traits::identity<type>{ };
462 }
else if constexpr( concepts::is_container_v<T> ) {
463 using type = json_base::json_array<typename T::value_type, T>;
464 return daw::traits::identity<type>{ };
465 }
else if constexpr( std::is_empty_v<T> and
466 std::is_default_constructible_v<T> ) {
468 using type = json_details::json_empty_class<T>;
469 return daw::traits::identity<type>{ };
470 }
else if constexpr( can_convert_to_tuple_v<T> ) {
471 using type = json_base::json_tuple<T>;
472 return daw::traits::identity<type>{ };
474 static_assert( daw::deduced_false_v<T>,
475 "Could not deduced data contract type and there is no "
476 "json_data_contract_specialization" );
481 using json_deduced_type =
482 typename DAW_TYPEOF( json_deduced_type_impl<T>( ) )::type;
485 DAW_CPP20_CONCEPT has_json_deduced_type_v =
486 not std::is_same_v<json_deduced_type<T>,
489 template<
typename... Ts>
490 DAW_CPP20_CONCEPT all_have_deduced_type_v =
491 ( has_json_deduced_type_v<Ts> and ... );
493 template<
typename JsonElement,
typename Container,
typename Constructor>
494 struct json_constructor<
495 json_base::
json_array<JsonElement, Container, Constructor>> {
496 using json_element_t = json_deduced_type<JsonElement>;
497 using json_element_parse_to_t = json_result_t<json_element_t>;
500 daw::conditional_t<std::is_same_v<Container, use_default>,
501 std::vector<json_element_parse_to_t>, Container>;
504 daw::conditional_t<std::is_same_v<use_default, Constructor>,
508 daw::is_callable_v<type, json_element_parse_to_t
const *,
509 json_element_parse_to_t
const *>,
510 "Constructor must support copy and/or move construction" );
513 template<
typename JsonElement,
typename Container,
typename Constructor>
515 json_base::
json_array<JsonElement, Container, Constructor>> {
516 using constructor_t =
typename json_constructor<
517 json_base::json_array<JsonElement, Container, Constructor>>::type;
518 using json_element_t = json_deduced_type<JsonElement>;
519 using json_element_parse_to_t =
520 typename json_result<json_element_t>::type;
522 std::invoke_result_t<constructor_t, json_element_parse_to_t
const *,
523 json_element_parse_to_t
const *>;
527 DAW_CPP20_CONCEPT has_unnamed_default_type_mapping_v =
528 has_json_deduced_type_v<T>;
530 template<
typename JsonMember>
531 using from_json_result_t = json_result_t<json_deduced_type<JsonMember>>;
533 template<
typename Constructor,
typename... Members>
534 using json_class_parse_result_impl2 =
535 std::invoke_result_t<Constructor, json_result_t<Members>...>;
537 template<
typename Constructor,
typename... Members>
538 using json_class_parse_result_impl =
539 daw::detected_t<json_class_parse_result_impl2, Constructor, Members...>;
541 template<
typename Constructor,
typename... Members>
542 struct could_not_construct_from_members_error;
544 template<
typename Constructor,
typename... Members>
545 using json_class_parse_result_t =
typename daw::conditional_t<
546 daw::is_callable_v<Constructor, json_result_t<Members>...>,
547 std::invoke_result<Constructor, json_result_t<Members>...>,
548 daw::traits::identity<could_not_construct_from_members_error<
549 Constructor, Members...>>>::type;
551 template<
typename JsonMember>
552 using dependent_member_t =
typename JsonMember::dependent_member;
554 template<
typename JsonMember,
typename =
void>
555 inline constexpr bool has_dependent_member_v =
false;
557 template<
typename JsonMember>
558 inline constexpr bool has_dependent_member_v<
559 JsonMember, std::void_t<dependent_member_t<JsonMember>>> =
true;
562 T::member_type::dependent_member );
564 template<
typename JsonMember>
566 inline constexpr bool has_dependent_member_v<
567 JsonMember DAW_ENABLEIF_S( is_json_nullable_v<JsonMember> )> =
568 has_nullable_dependent_member_v<JsonMember>;
570 template<
typename Constructor>
571 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr auto
572 construct_nullable_empty( ) {
573 if constexpr( daw::is_callable_v<
575 concepts::construct_nullable_with_empty_t> ) {
576 return Constructor{ }( concepts::construct_nullable_with_empty );
578 return Constructor{ }( );