53 namespace json_details {
56 number_parse_type_impl_test( ) {
57 if constexpr( daw::is_floating_point_v<T> ) {
58 return JsonParseTypes::Real;
59 }
else if constexpr( daw::is_signed_v<T> ) {
60 return JsonParseTypes::Signed;
62 static_assert( daw::is_unsigned_v<T> );
63 return JsonParseTypes::Unsigned;
68 DAW_ATTRIB_INLINE DAW_CONSTEVAL
JsonParseTypes number_parse_type_test( ) {
69 if constexpr( std::is_enum_v<T> ) {
70 return number_parse_type_impl_test<std::underlying_type_t<T>>( );
72 return number_parse_type_impl_test<T>( );
78 number_parse_type_test<T>( );
80 template<
typename,
typename =
void>
81 struct json_deduced_type_map {
82 static constexpr bool is_null =
false;
83 static constexpr auto parse_type = JsonParseTypes::Unknown;
85 static constexpr bool type_map_found =
false;
88 template<
typename JsonType>
90 struct json_deduced_type_map<
91 JsonType DAW_ENABLEIF_S( is_a_json_type_v<JsonType> )> {
92 static constexpr bool is_null =
false;
93 static constexpr auto parse_type = JsonParseTypes::Unknown;
95 using type = JsonType;
96 static constexpr bool type_map_found =
true;
101 struct json_deduced_type_map<
102 T DAW_ENABLEIF_S( has_json_data_contract_trait_v<T> )> {
103 static constexpr bool is_null =
false;
105 static_assert( is_json_member_list_v<type>,
106 "Expected a JSON member list" );
107 static constexpr auto parse_type = JsonParseTypes::Unknown;
109 static constexpr bool type_map_found =
true;
113 struct json_deduced_type_map<
daw::string_view> {
114 static constexpr bool is_null =
false;
115 static constexpr auto parse_type = JsonParseTypes::StringRaw;
117 static constexpr bool type_map_found =
true;
121 struct json_deduced_type_map<
std::string_view> {
122 static constexpr bool is_null =
false;
123 static constexpr auto parse_type = JsonParseTypes::StringRaw;
125 static constexpr bool type_map_found =
true;
129 struct json_deduced_type_map<
std::string> {
130 static constexpr bool is_null =
false;
131 static constexpr auto parse_type = JsonParseTypes::StringEscaped;
133 static constexpr bool type_map_found =
true;
137 struct json_deduced_type_map<bool> {
138 static constexpr bool is_null =
false;
139 static constexpr auto parse_type = JsonParseTypes::Bool;
140 static constexpr bool type_map_found =
true;
145#if defined( _LIBCPP_VERSION )
147 struct json_deduced_type_map<
148 typename
std::vector<bool>::const_reference> {
150 static constexpr bool is_null =
false;
151 static constexpr auto parse_type = JsonParseTypes::Bool;
153 static constexpr bool type_map_found =
true;
157 template<
typename Integer>
159 not json_details::has_json_data_contract_trait_v<Integer> and
160 daw::is_integral_v<Integer> )
161 struct json_deduced_type_map<Integer DAW_ENABLEIF_S(
162 not json_details::has_json_data_contract_trait_v<Integer> and
163 daw::is_integral_v<Integer> )> {
164 static constexpr bool is_null =
false;
165 static constexpr auto parse_type = daw::is_signed_v<Integer>
166 ? JsonParseTypes::Signed
167 : JsonParseTypes::Unsigned;
169 static constexpr bool type_map_found =
true;
172 template<
typename Enum>
173 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Enum> and
174 std::is_enum_v<Enum> )
175 struct json_deduced_type_map<Enum DAW_ENABLEIF_S(
176 not json_details::has_json_data_contract_trait_v<Enum> and
177 std::is_enum_v<Enum> )> {
178 static constexpr bool is_null =
false;
179 static constexpr auto parse_type =
180 daw::is_signed_v<std::underlying_type<Enum>>
181 ? JsonParseTypes::Signed
182 : JsonParseTypes::Unsigned;
184 static constexpr bool type_map_found =
true;
187 template<
typename FloatingPo
int>
189 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
190 daw::is_floating_point_v<FloatingPoint> )
191 struct json_deduced_type_map<FloatingPoint DAW_ENABLEIF_S(
192 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
193 daw::is_floating_point_v<FloatingPoint> )> {
194 static constexpr bool is_null =
false;
195 static constexpr auto parse_type = JsonParseTypes::Real;
197 static constexpr bool type_map_found =
true;
200 template<
typename Tuple>
201 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Tuple> and
203 struct json_deduced_type_map<Tuple DAW_ENABLEIF_S(
204 not json_details::has_json_data_contract_trait_v<Tuple> and
205 is_tuple_v<Tuple> )> {
206 static constexpr bool is_null =
false;
207 static constexpr auto parse_type = JsonParseTypes::Tuple;
209 static constexpr bool type_map_found =
true;
212 namespace container_detect {
214 using is_string_test =
215 decltype( (void)( std::begin( std::declval<T &>( ) ) ),
216 (
void)( std::end( std::declval<T &>( ) ) ),
217 std::declval<typename T::value_type>( ) );
220 template<
typename String>
221 DAW_CPP20_CONCEPT is_string_v = std::is_same_v<
222 char, daw::detected_t<container_detect::is_string_test, String>>;
225 is_associative_container_v,
226 ( (
void)( std::begin( std::declval<T &>( ) ) ),
227 (
void)( std::end( std::declval<T &>( ) ) ),
228 (
void)( std::declval<typename T::value_type>( ) ),
229 (
void)( std::declval<typename T::key_type>( ) ),
230 (
void)( std::declval<typename T::mapped_type>( ) ) ) );
232 template<
typename AssociativeContainer>
233 DAW_REQUIRES( not has_json_data_contract_trait_v<AssociativeContainer> and
234 is_associative_container_v<AssociativeContainer> )
235 struct json_deduced_type_map<AssociativeContainer DAW_ENABLEIF_S(
236 not has_json_data_contract_trait_v<AssociativeContainer> and
237 is_associative_container_v<AssociativeContainer> )> {
238 static constexpr bool is_null =
false;
239 using key =
typename AssociativeContainer::key_type;
240 using value =
typename AssociativeContainer::mapped_type;
241 static constexpr auto parse_type = JsonParseTypes::KeyValue;
243 static constexpr bool type_map_found =
true;
247 DAW_CPP20_CONCEPT is_deduced_array_v =
248 not has_json_data_contract_trait_v<T> and
249 not is_associative_container_v<T> and concepts::is_container_v<T> and
252 template<
typename Container>
254 struct json_deduced_type_map<
255 Container DAW_ENABLEIF_S( is_deduced_array_v<Container> )> {
256 static constexpr bool is_null =
false;
257 using value =
typename Container::value_type;
258 static constexpr auto parse_type = JsonParseTypes::Array;
260 static constexpr bool type_map_found =
true;
264 DAW_CPP20_CONCEPT has_nullable_type_map_v =
265 concepts::is_nullable_value_v<T> and
266 not has_json_data_contract_trait_v<T> and
267 daw::is_detected_v<json_deduced_type_map,
268 concepts::nullable_value_type_t<T>>;
272 struct json_deduced_type_map<
273 T DAW_ENABLEIF_S( has_nullable_type_map_v<T> )> {
274 static constexpr bool is_null =
true;
275 using sub_type = concepts::nullable_value_type_t<T>;
276 using type = json_deduced_type_map<sub_type>;
277 static constexpr auto parse_type = type::parse_type;
278 static constexpr bool type_map_found =
true;
282 DAW_CPP20_CONCEPT has_deduced_type_mapping_v =
283 json_deduced_type_map<T>::type_map_found;
285 template<
typename... Ts>
286 DAW_CPP20_CONCEPT are_deduced_type_mapped_v =
287 ( has_deduced_type_mapping_v<Ts> and ... );
289 template<
typename Mapped,
bool Found = true>
290 struct json_link_quick_map_type {
291 static constexpr bool value = Found;
292 using mapped_type = Mapped;
295 template<JsonParseTypes Value>
296 DAW_CPP20_CONCEPT is_arithmetic_parse_type_v =
297 daw::traits::equal_to_any_of_v<Value, JsonParseTypes::Signed,
298 JsonParseTypes::Unsigned,
299 JsonParseTypes::Real>;
302 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_link_quick_map( )
noexcept {
303 if constexpr( is_a_json_type_v<T> ) {
304 return json_link_quick_map_type<T>{ };
305 }
else if constexpr( has_deduced_type_mapping_v<T> ) {
306 using mapped_type_t = json_deduced_type_map<T>;
307 using parse_type = daw::constant<mapped_type_t::parse_type>;
308 using is_null = daw::constant<mapped_type_t::is_null>;
309 if constexpr( parse_type::value == JsonParseTypes::Unknown ) {
310 if constexpr( is_null::value ) {
311 if constexpr( has_json_data_contract_trait_v<
312 typename mapped_type_t::sub_type> ) {
313 return json_link_quick_map_type<
314 json_base::json_class_null<T>>{ };
316 return json_link_quick_map_type<json_base::json_raw_null<T>>{ };
319 return json_link_quick_map_type<json_base::json_raw<T>>{ };
321 }
else if constexpr( parse_type::value ==
322 JsonParseTypes::StringRaw ) {
323 if constexpr( is_null::value ) {
324 return json_link_quick_map_type<
325 json_base::json_string_raw_null<T>>{ };
327 return json_link_quick_map_type<json_base::json_string_raw<T>>{ };
329 }
else if constexpr( parse_type::value ==
330 JsonParseTypes::StringEscaped ) {
331 if constexpr( is_null::value ) {
332 return json_link_quick_map_type<
333 json_base::json_string_null<T>>{ };
335 return json_link_quick_map_type<json_base::json_string<T>>{ };
337 }
else if constexpr( parse_type::value == JsonParseTypes::StringInsitu ) {
338 if constexpr( is_null::value ) {
339 return json_link_quick_map_type<json_base::json_string_null<T>>{ };
341 return json_link_quick_map_type<json_base::json_string<T>>{ };
343 }
else if constexpr( parse_type::value == JsonParseTypes::Bool ) {
344 if constexpr( is_null::value ) {
345 return json_link_quick_map_type<json_base::json_bool_null<T>>{ };
347 return json_link_quick_map_type<json_base::json_bool<T>>{ };
349 }
else if constexpr( is_arithmetic_parse_type_v<parse_type::value> ) {
350 if constexpr( is_null::value ) {
351 return json_link_quick_map_type<
352 json_base::json_number_null<T>>{ };
354 return json_link_quick_map_type<json_base::json_number<T>>{ };
356 }
else if constexpr( parse_type::value == JsonParseTypes::Tuple ) {
357 if constexpr( is_null::value ) {
358 return json_link_quick_map_type<json_base::json_tuple_null<T>>{ };
360 return json_link_quick_map_type<json_base::json_tuple<T>>{ };
362 }
else if constexpr( parse_type::value == JsonParseTypes::KeyValue ) {
363 if constexpr( is_null::value ) {
364 using b_t =
typename mapped_type_t::type;
365 using k_t =
typename b_t::key;
366 using v_t =
typename b_t::value;
367 return json_link_quick_map_type<
368 json_base::json_key_value_null<T, v_t, k_t>>{ };
370 using k_t =
typename mapped_type_t::key;
371 using v_t =
typename mapped_type_t::value;
372 return json_link_quick_map_type<
373 json_base::json_key_value<T, v_t, k_t>>{ };
375 }
else if constexpr( parse_type::value == JsonParseTypes::Array ) {
376 if constexpr( is_null::value ) {
377 using b_t =
typename mapped_type_t::type;
378 using v_t =
typename b_t::value;
379 return json_link_quick_map_type<
380 json_base::json_nullable<
381 T, json_base::json_array<v_t, json_details::unwrapped_t<T>>>>{ };
383 using v_t =
typename mapped_type_t::value;
384 return json_link_quick_map_type<json_base::json_array<v_t, T>>{ };
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>{ };
394#if defined( DAW_JSON_HAS_REFLECTION )
395 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
396 return json_link_quick_map_type<
397 json_base::json_reflected_class<T>>{ };
400 return json_link_quick_map_type<void, false>{ };
406 DAW_CPP20_CONCEPT has_json_link_quick_map_v =
407 decltype( json_link_quick_map<T>( ) )::value;
411 using json_link_quick_map_t =
412 typename decltype( json_link_quick_map<T>( ) )::mapped_type;
414 template<
typename JsonType>
415 struct json_class_map_type {
420 struct is_json_class_map : std::false_type {};
424 inline constexpr bool is_json_class_map_v =
425 has_json_data_contract_trait_v<T> and
426 is_json_class_map_v<json_data_contract_trait_t<T>>;
429 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_deduced_type_impl( )
noexcept {
430 if constexpr( is_a_basic_json_value<T> ) {
431 return daw::traits::identity<json_base::json_raw<T>>{ };
432#if defined( DAW_JSON_HAS_REFLECTION )
433 }
else if constexpr( refl_details::HasTypeLevelAnnotation<T> ) {
434 return daw::traits::identity<
435 refl_details::type_annotation_mapping_t<T>>{ };
437 }
else if constexpr( is_an_ordered_member_v<T> ) {
439 return daw::traits::identity<type>{ };
440 }
else if constexpr( has_json_data_contract_trait_v<T> ) {
441 static_assert( not std::is_same_v<T, void> );
443 using type = json_base::json_class<T>;
445 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
446 "Detection failure" );
447 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
448 "Detection failure" );
449 return daw::traits::identity<type>{ };
450 }
else if constexpr( has_json_link_quick_map_v<T> ) {
451 static_assert( not std::is_same_v<T, void> );
452 using type = json_link_quick_map_t<T>;
453 using rcvref_type = remove_cvref_t<type>;
454 static_assert( not std::is_same_v<rcvref_type, void>,
455 "Detection failure" );
456 static_assert( not is_nonesuch_v<rcvref_type>,
"Detection failure" );
457 return daw::traits::identity<type>{ };
458 }
else if constexpr( is_a_json_type_v<T> ) {
459 static_assert( not std::is_same_v<T, void> );
461 typename daw::conditional_t<is_json_class_map_v<T>,
462 json_class_map_type<T>,
463 daw::traits::identity<T>>::type;
464 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
465 "Detection failure" );
466 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
467 "Detection failure" );
468 return daw::traits::identity<type>{ };
469 }
else if constexpr( concepts::is_nullable_value_v<T> ) {
470 using value_type = concepts::nullable_value_type_t<T>;
472 typename decltype( json_deduced_type_impl<value_type>( ) )::type;
473 using type = json_base::json_nullable<T, sub_type>;
474 return daw::traits::identity<type>{ };
475 }
else if constexpr( concepts::is_container_v<T> ) {
476 using type = json_base::json_array<typename T::value_type, T>;
477 return daw::traits::identity<type>{ };
478 }
else if constexpr( std::is_empty_v<T> and
479 std::is_default_constructible_v<T> ) {
481 using type = json_details::json_empty_class<T>;
482 return daw::traits::identity<type>{ };
483#if not defined( DAW_JSON_HAS_REFLECTION )
484 }
else if constexpr( can_convert_to_tuple_v<T> ) {
485 using type = json_base::json_tuple<T>;
486 return daw::traits::identity<type>{ };
489 static_assert( daw::deduced_false_v<T>,
490 "Could not deduced data contract type and there is no "
491 "json_data_contract_specialization" );
496 using json_deduced_type =
497 typename DAW_TYPEOF( json_deduced_type_impl<T>( ) )::type;
500 DAW_CPP20_CONCEPT has_json_deduced_type_v =
501 not std::is_same_v<json_deduced_type<T>,
504 template<
typename... Ts>
505 DAW_CPP20_CONCEPT all_have_deduced_type_v =
506 ( has_json_deduced_type_v<Ts> and ... );
508 template<
typename JsonElement,
typename Container,
typename Constructor>
509 struct json_constructor<
510 json_base::
json_array<JsonElement, Container, Constructor>> {
511 using json_element_t = json_deduced_type<JsonElement>;
512 using json_element_parse_to_t = json_result_t<json_element_t>;
515 daw::conditional_t<std::is_same_v<Container, use_default>,
516 std::vector<json_element_parse_to_t>, Container>;
519 daw::conditional_t<std::is_same_v<use_default, Constructor>,
523 daw::is_callable_v<type, json_element_parse_to_t
const *,
524 json_element_parse_to_t
const *>,
525 "Constructor must support copy and/or move construction" );
528 template<
typename JsonElement,
typename Container,
typename Constructor>
530 json_base::
json_array<JsonElement, Container, Constructor>> {
531 using constructor_t =
typename json_constructor<
532 json_base::json_array<JsonElement, Container, Constructor>>::type;
533 using json_element_t = json_deduced_type<JsonElement>;
534 using json_element_parse_to_t =
535 typename json_result<json_element_t>::type;
537 std::invoke_result_t<constructor_t, json_element_parse_to_t
const *,
538 json_element_parse_to_t
const *>;
542 DAW_CPP20_CONCEPT has_unnamed_default_type_mapping_v =
543 has_json_deduced_type_v<T>;
545 template<
typename JsonMember>
546 using from_json_result_t = json_result_t<json_deduced_type<JsonMember>>;
548 template<
typename Constructor,
typename... Members>
549 using json_class_parse_result_impl2 =
550 std::invoke_result_t<Constructor, json_result_t<Members>...>;
552 template<
typename Constructor,
typename... Members>
553 using json_class_parse_result_impl =
554 daw::detected_t<json_class_parse_result_impl2, Constructor, Members...>;
556 template<
typename Constructor,
typename... Members>
557 struct could_not_construct_from_members_error;
559 template<
typename Constructor,
typename... Members>
560 using json_class_parse_result_t =
typename daw::conditional_t<
561 daw::is_callable_v<Constructor, json_result_t<Members>...>,
562 std::invoke_result<Constructor, json_result_t<Members>...>,
563 daw::traits::identity<could_not_construct_from_members_error<
564 Constructor, Members...>>>::type;
566 template<
typename JsonMember>
567 using dependent_member_t =
typename JsonMember::dependent_member;
569 template<
typename JsonMember,
typename =
void>
570 inline constexpr bool has_dependent_member_v =
false;
572 template<
typename JsonMember>
573 inline constexpr bool has_dependent_member_v<
574 JsonMember, std::void_t<dependent_member_t<JsonMember>>> =
true;
577 T::member_type::dependent_member );
579 template<
typename JsonMember>
581 inline constexpr bool has_dependent_member_v<
582 JsonMember DAW_ENABLEIF_S( is_json_nullable_v<JsonMember> )> =
583 has_nullable_dependent_member_v<JsonMember>;
585 template<
typename Constructor>
586 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr auto
587 construct_nullable_empty( ) {
588 if constexpr( daw::is_callable_v<
590 concepts::construct_nullable_with_empty_t> ) {
591 return Constructor{ }( concepts::construct_nullable_with_empty );
593 return Constructor{ }( );