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 = json_base_type_t<mapped_type_t>;
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 = json_base_type_t<mapped_type_t>;
378 using v_t =
typename b_t::value;
379 return json_link_quick_map_type<
380 json_base::json_nullable<T, json_base::json_array<v_t, T>>>{ };
382 using v_t =
typename mapped_type_t::value;
383 return json_link_quick_map_type<json_base::json_array<v_t, T>>{ };
385#if defined( DAW_JSON_HAS_REFLECTION )
386 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
387 return json_link_quick_map_type<
388 json_base::json_reflected_class<T>>{ };
391 return json_link_quick_map_type<void, false>{ };
393#if defined( DAW_JSON_HAS_REFLECTION )
394 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
395 return json_link_quick_map_type<
396 json_base::json_reflected_class<T>>{ };
399 return json_link_quick_map_type<void, false>{ };
405 DAW_CPP20_CONCEPT has_json_link_quick_map_v =
406 decltype( json_link_quick_map<T>( ) )::value;
410 using json_link_quick_map_t =
411 typename decltype( json_link_quick_map<T>( ) )::mapped_type;
413 template<
typename JsonType>
414 struct json_class_map_type {
419 struct is_json_class_map : std::false_type {};
423 inline constexpr bool is_json_class_map_v =
424 has_json_data_contract_trait_v<T> and
425 is_json_class_map_v<json_data_contract_trait_t<T>>;
428 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_deduced_type_impl( )
noexcept {
429 if constexpr( is_a_basic_json_value<T> ) {
430 return daw::traits::identity<json_base::json_raw<T>>{ };
431 }
else if constexpr( is_an_ordered_member_v<T> ) {
433 return daw::traits::identity<type>{ };
434 }
else if constexpr( has_json_data_contract_trait_v<T> ) {
435 static_assert( not std::is_same_v<T, void> );
437 using type = json_base::json_class<T>;
439 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
440 "Detection failure" );
441 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
442 "Detection failure" );
443 return daw::traits::identity<type>{ };
444 }
else if constexpr( has_json_link_quick_map_v<T> ) {
445 static_assert( not std::is_same_v<T, void> );
446 using type = json_link_quick_map_t<T>;
447 using rcvref_type = remove_cvref_t<type>;
448 static_assert( not std::is_same_v<rcvref_type, void>,
449 "Detection failure" );
450 static_assert( not is_nonesuch_v<rcvref_type>,
"Detection failure" );
451 return daw::traits::identity<type>{ };
452 }
else if constexpr( is_a_json_type_v<T> ) {
453 static_assert( not std::is_same_v<T, void> );
455 typename daw::conditional_t<is_json_class_map_v<T>,
456 json_class_map_type<T>,
457 daw::traits::identity<T>>::type;
458 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
459 "Detection failure" );
460 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
461 "Detection failure" );
462 return daw::traits::identity<type>{ };
463 }
else if constexpr( concepts::is_nullable_value_v<T> ) {
464 using value_type = concepts::nullable_value_type_t<T>;
466 typename decltype( json_deduced_type_impl<value_type>( ) )::type;
467 using type = json_base::json_nullable<T, sub_type>;
468 return daw::traits::identity<type>{ };
469 }
else if constexpr( concepts::is_container_v<T> ) {
470 using type = json_base::json_array<typename T::value_type, T>;
471 return daw::traits::identity<type>{ };
472 }
else if constexpr( std::is_empty_v<T> and
473 std::is_default_constructible_v<T> ) {
475 using type = json_details::json_empty_class<T>;
476 return daw::traits::identity<type>{ };
477#if not defined( DAW_JSON_HAS_REFLECTION )
478 }
else if constexpr( can_convert_to_tuple_v<T> ) {
479 using type = json_base::json_tuple<T>;
480 return daw::traits::identity<type>{ };
483 static_assert( daw::deduced_false_v<T>,
484 "Could not deduced data contract type and there is no "
485 "json_data_contract_specialization" );
490 using json_deduced_type =
491 typename DAW_TYPEOF( json_deduced_type_impl<T>( ) )::type;
494 DAW_CPP20_CONCEPT has_json_deduced_type_v =
495 not std::is_same_v<json_deduced_type<T>,
498 template<
typename... Ts>
499 DAW_CPP20_CONCEPT all_have_deduced_type_v =
500 ( has_json_deduced_type_v<Ts> and ... );
502 template<
typename JsonElement,
typename Container,
typename Constructor>
503 struct json_constructor<
504 json_base::
json_array<JsonElement, Container, Constructor>> {
505 using json_element_t = json_deduced_type<JsonElement>;
506 using json_element_parse_to_t = json_result_t<json_element_t>;
509 daw::conditional_t<std::is_same_v<Container, use_default>,
510 std::vector<json_element_parse_to_t>, Container>;
513 daw::conditional_t<std::is_same_v<use_default, Constructor>,
517 daw::is_callable_v<type, json_element_parse_to_t
const *,
518 json_element_parse_to_t
const *>,
519 "Constructor must support copy and/or move construction" );
522 template<
typename JsonElement,
typename Container,
typename Constructor>
524 json_base::
json_array<JsonElement, Container, Constructor>> {
525 using constructor_t =
typename json_constructor<
526 json_base::json_array<JsonElement, Container, Constructor>>::type;
527 using json_element_t = json_deduced_type<JsonElement>;
528 using json_element_parse_to_t =
529 typename json_result<json_element_t>::type;
531 std::invoke_result_t<constructor_t, json_element_parse_to_t
const *,
532 json_element_parse_to_t
const *>;
536 DAW_CPP20_CONCEPT has_unnamed_default_type_mapping_v =
537 has_json_deduced_type_v<T>;
539 template<
typename JsonMember>
540 using from_json_result_t = json_result_t<json_deduced_type<JsonMember>>;
542 template<
typename Constructor,
typename... Members>
543 using json_class_parse_result_impl2 =
544 std::invoke_result_t<Constructor, json_result_t<Members>...>;
546 template<
typename Constructor,
typename... Members>
547 using json_class_parse_result_impl =
548 daw::detected_t<json_class_parse_result_impl2, Constructor, Members...>;
550 template<
typename Constructor,
typename... Members>
551 struct could_not_construct_from_members_error;
553 template<
typename Constructor,
typename... Members>
554 using json_class_parse_result_t =
typename daw::conditional_t<
555 daw::is_callable_v<Constructor, json_result_t<Members>...>,
556 std::invoke_result<Constructor, json_result_t<Members>...>,
557 daw::traits::identity<could_not_construct_from_members_error<
558 Constructor, Members...>>>::type;
560 template<
typename JsonMember>
561 using dependent_member_t =
typename JsonMember::dependent_member;
563 template<
typename JsonMember,
typename =
void>
564 inline constexpr bool has_dependent_member_v =
false;
566 template<
typename JsonMember>
567 inline constexpr bool has_dependent_member_v<
568 JsonMember, std::void_t<dependent_member_t<JsonMember>>> =
true;
571 T::member_type::dependent_member );
573 template<
typename JsonMember>
575 inline constexpr bool has_dependent_member_v<
576 JsonMember DAW_ENABLEIF_S( is_json_nullable_v<JsonMember> )> =
577 has_nullable_dependent_member_v<JsonMember>;
579 template<
typename Constructor>
580 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr auto
581 construct_nullable_empty( ) {
582 if constexpr( daw::is_callable_v<
584 concepts::construct_nullable_with_empty_t> ) {
585 return Constructor{ }( concepts::construct_nullable_with_empty );
587 return Constructor{ }( );