DAW JSON Link
Loading...
Searching...
No Matches
daw_json_parse_common.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
12
14
28
29#include <daw/cpp_17.h>
30#include <daw/daw_allocator_construct.h>
31#include <daw/daw_arith_traits.h>
32#include <daw/daw_callable.h>
33#include <daw/daw_consteval.h>
34#include <daw/daw_cpp20_concept.h>
35#include <daw/daw_cpp_feature_check.h>
36#include <daw/daw_enable_requires.h>
37#include <daw/daw_fwd_pack_apply.h>
38#include <daw/daw_move.h>
39#include <daw/daw_scope_guard.h>
40#include <daw/daw_string_view.h>
41#include <daw/daw_traits.h>
42
43#include <array>
44#include <cstddef>
45#include <iterator>
46#include <optional>
47#include <string>
48#include <string_view>
49#include <vector>
50
51namespace daw::json {
52 inline namespace DAW_JSON_VER {
53 namespace json_details {
54 template<typename T>
55 DAW_ATTRIB_INLINE DAW_CONSTEVAL JsonParseTypes
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;
61 } else {
62 static_assert( daw::is_unsigned_v<T> );
63 return JsonParseTypes::Unsigned;
64 }
65 }
66
67 template<typename T>
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>>( );
71 } else {
72 return number_parse_type_impl_test<T>( );
73 }
74 }
75
76 template<typename T>
77 inline constexpr JsonParseTypes number_parse_type_v =
78 number_parse_type_test<T>( );
79
80 template<typename, typename AllowRawString, typename = void>
81 struct json_deduced_type_map {
82 static constexpr bool is_null = false;
83 static constexpr auto parse_type = JsonParseTypes::Unknown;
84
85 static constexpr bool type_map_found = false;
86 };
87
88 template<typename JsonType, typename AllowRawString>
89 DAW_REQUIRES( is_a_json_type_v<JsonType> )
90 struct json_deduced_type_map<
91 JsonType, AllowRawString DAW_ENABLEIF_S( is_a_json_type_v<JsonType> )> {
92 static constexpr bool is_null = false;
93 static constexpr auto parse_type = JsonParseTypes::Unknown;
94
95 using type = JsonType;
96 static constexpr bool type_map_found = true;
97 };
98
99 template<typename T, typename AllowRawString>
100 DAW_REQUIRES( has_json_data_contract_trait_v<T> )
101 struct json_deduced_type_map<
102 T, AllowRawString DAW_ENABLEIF_S( has_json_data_contract_trait_v<T> )> {
103 static constexpr bool is_null = false;
104 using type = typename json_data_contract<T>::type;
105 static_assert( is_json_member_list_v<type>,
106 "Expected a JSON member list" );
107 static constexpr auto parse_type = JsonParseTypes::Unknown;
108
109 static constexpr bool type_map_found = true;
110 };
111
112 template<>
113 struct json_deduced_type_map<daw::string_view, std::true_type> {
114 static constexpr bool is_null = false;
115 static constexpr auto parse_type = JsonParseTypes::StringRaw;
116
117 static constexpr bool type_map_found = true;
118 };
119
120 template<>
121 struct json_deduced_type_map<daw::string_view, std::false_type> {
122 static constexpr bool is_null = false;
123 static constexpr auto parse_type = JsonParseTypes::StringInsitu;
124
125 static constexpr bool type_map_found = true;
126 };
127
128 template<>
129 struct json_deduced_type_map<std::string_view, std::true_type> {
130 static constexpr bool is_null = false;
131 static constexpr auto parse_type = JsonParseTypes::StringRaw;
132
133 static constexpr bool type_map_found = true;
134 };
135
136 template<>
137 struct json_deduced_type_map<std::string_view, std::false_type> {
138 static constexpr bool is_null = false;
139 static constexpr auto parse_type = JsonParseTypes::StringInsitu;
140
141 static constexpr bool type_map_found = true;
142 };
143
146 template<>
147 struct json_deduced_type_map<char, std::false_type> {
148 static constexpr bool is_null = false;
149 static constexpr auto parse_type = JsonParseTypes::StringInsitu;
150
151 static constexpr bool type_map_found = true;
152 };
153
154 template<typename AllowRawString>
155 struct json_deduced_type_map<std::string, AllowRawString> {
156 static constexpr bool is_null = false;
157 static constexpr auto parse_type = JsonParseTypes::StringEscaped;
158
159 static constexpr bool type_map_found = true;
160 };
161
162 template<typename AllowRawString>
163 struct json_deduced_type_map<bool, AllowRawString> {
164 static constexpr bool is_null = false;
165 static constexpr auto parse_type = JsonParseTypes::Bool;
166 static constexpr bool type_map_found = true;
167 };
168
169 // libc++ has a non-conforming vector<bool>::const_reference as it isn't
170 // bool https://bugs.llvm.org/show_bug.cgi?id=16077
171#if defined( _LIBCPP_VERSION )
172 template<typename AllowRawString>
173 struct json_deduced_type_map<typename std::vector<bool>::const_reference,
174 AllowRawString> {
175
176 static constexpr bool is_null = false;
177 static constexpr auto parse_type = JsonParseTypes::Bool;
178
179 static constexpr bool type_map_found = true;
180 };
181#endif
182
183 template<typename Integer, typename AllowRawString>
185 not json_details::has_json_data_contract_trait_v<Integer> and
186 daw::is_integral_v<Integer> )
187 struct json_deduced_type_map<
188 Integer, AllowRawString DAW_ENABLEIF_S(
189 not json_details::has_json_data_contract_trait_v<Integer> and
190 daw::is_integral_v<Integer> )> {
191 static constexpr bool is_null = false;
192 static constexpr auto parse_type = daw::is_signed_v<Integer>
193 ? JsonParseTypes::Signed
194 : JsonParseTypes::Unsigned;
195
196 static constexpr bool type_map_found = true;
197 };
198
199 template<typename Enum, typename AllowRawString>
200 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Enum> and
201 std::is_enum_v<Enum> )
202 struct json_deduced_type_map<
203 Enum, AllowRawString DAW_ENABLEIF_S(
204 not json_details::has_json_data_contract_trait_v<Enum> and
205 std::is_enum_v<Enum> )> {
206 static constexpr bool is_null = false;
207 static constexpr auto parse_type =
208 daw::is_signed_v<std::underlying_type<Enum>>
209 ? JsonParseTypes::Signed
210 : JsonParseTypes::Unsigned;
211
212 static constexpr bool type_map_found = true;
213 };
214
215 template<typename FloatingPoint, typename AllowRawString>
217 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
218 daw::is_floating_point_v<FloatingPoint> )
219 struct json_deduced_type_map<
220 FloatingPoint,
221 AllowRawString DAW_ENABLEIF_S(
222 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
223 daw::is_floating_point_v<FloatingPoint> )> {
224 static constexpr bool is_null = false;
225 static constexpr auto parse_type = JsonParseTypes::Real;
226
227 static constexpr bool type_map_found = true;
228 };
229
230 template<typename Tuple, typename AllowRawString>
231 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Tuple> and
232 is_tuple_v<Tuple> )
233 struct json_deduced_type_map<
234 Tuple, AllowRawString DAW_ENABLEIF_S(
235 not json_details::has_json_data_contract_trait_v<Tuple> and
236 is_tuple_v<Tuple> )> {
237 static constexpr bool is_null = false;
238 static constexpr auto parse_type = JsonParseTypes::Tuple;
239
240 static constexpr bool type_map_found = true;
241 };
242
243 namespace container_detect {
244 template<typename T>
245 using is_string_test =
246 decltype( (void)( std::begin( std::declval<T &>( ) ) ),
247 (void)( std::end( std::declval<T &>( ) ) ),
248 std::declval<typename T::value_type>( ) );
249 } // namespace container_detect
250
251 template<typename String>
252 DAW_CPP20_CONCEPT is_string_v = std::is_same_v<
253 char, daw::detected_t<container_detect::is_string_test, String>>;
254
256 is_associative_container_v,
257 ( (void)( std::begin( std::declval<T &>( ) ) ),
258 (void)( std::end( std::declval<T &>( ) ) ),
259 (void)( std::declval<typename T::value_type>( ) ),
260 (void)( std::declval<typename T::key_type>( ) ),
261 (void)( std::declval<typename T::mapped_type>( ) ) ) );
262
263 template<typename AssociativeContainer, typename AllowRawString>
264 DAW_REQUIRES( not has_json_data_contract_trait_v<AssociativeContainer> and
265 is_associative_container_v<AssociativeContainer> )
266 struct json_deduced_type_map<
267 AssociativeContainer,
268 AllowRawString DAW_ENABLEIF_S(
269 not has_json_data_contract_trait_v<AssociativeContainer> and
270 is_associative_container_v<AssociativeContainer> )> {
271 static constexpr bool is_null = false;
272 using key = typename AssociativeContainer::key_type;
273 using value = typename AssociativeContainer::mapped_type;
274 static constexpr auto parse_type = JsonParseTypes::KeyValue;
275
276 static constexpr bool type_map_found = true;
277 };
278
279 template<typename T>
280 DAW_CPP20_CONCEPT is_deduced_array_v =
281 not has_json_data_contract_trait_v<T> and
282 not is_associative_container_v<T> and concepts::is_container_v<T> and
283 not is_string_v<T>;
284
285 template<typename Container, typename AllowRawString>
286 DAW_REQUIRES( is_deduced_array_v<Container> )
287 struct json_deduced_type_map<
288 Container,
289 AllowRawString DAW_ENABLEIF_S( is_deduced_array_v<Container> )> {
290 static constexpr bool is_null = false;
291 using value = typename Container::value_type;
292 static constexpr auto parse_type = JsonParseTypes::Array;
293
294 static constexpr bool type_map_found = true;
295 };
296
297#if defined( DAW_JSON_USE_CONCEPTS )
298 template<typename T, typename AllowRawString>
299 inline constexpr bool detected_deduced_type_map_v = requires {
300 requires json_deduced_type_map<T, AllowRawString>::type_map_found;
301 };
302#else
303 template<typename, typename, typename = void>
304 inline constexpr bool detected_deduced_type_map_v = false;
305
306 template<typename T, typename AllowRawString>
307 inline constexpr bool detected_deduced_type_map_v<
308 T, AllowRawString,
309 std::void_t<decltype( json_deduced_type_map<
310 T, AllowRawString>::type_map_found )>> =
311 json_deduced_type_map<T, AllowRawString>::type_map_found;
312#endif
313 template<typename T, typename AllowRawString>
314 DAW_CPP20_CONCEPT has_nullable_type_map_v =
315 concepts::is_nullable_value_v<T> and
316 not has_json_data_contract_trait_v<T> and
317 detected_deduced_type_map_v<concepts::nullable_value_type_t<T>,
318 AllowRawString>;
319
320 template<typename T, typename AllowRawString>
321 DAW_REQUIRES( has_nullable_type_map_v<T, AllowRawString> )
322 struct json_deduced_type_map<
323 T, AllowRawString DAW_ENABLEIF_S(
324 has_nullable_type_map_v<T, AllowRawString> )> {
325 static constexpr bool is_null = true;
326 using sub_type = concepts::nullable_value_type_t<T>;
327 using type = json_deduced_type_map<sub_type, AllowRawString>;
328 static constexpr auto parse_type = type::parse_type;
329 static constexpr bool type_map_found = true;
330 };
331
332 template<typename T, typename AllowRawString = std::true_type>
333 DAW_CPP20_CONCEPT has_deduced_type_mapping_v =
334 json_deduced_type_map<T, AllowRawString>::type_map_found;
335
336 template<typename... Ts>
337 DAW_CPP20_CONCEPT are_deduced_type_mapped_v =
338 ( has_deduced_type_mapping_v<Ts> and ... );
339
340 template<typename Mapped, bool Found = true>
341 struct json_link_quick_map_type {
342 static constexpr bool value = Found;
343 using mapped_type = Mapped;
344 };
345
346 template<JsonParseTypes Value>
347 DAW_CPP20_CONCEPT is_arithmetic_parse_type_v =
348 daw::traits::equal_to_any_of_v<Value, JsonParseTypes::Signed,
349 JsonParseTypes::Unsigned,
350 JsonParseTypes::Real>;
351
352 template<typename T, typename AllowRawString = std::true_type>
353 DAW_ATTRIB_INLINE DAW_CONSTEVAL auto json_deduced_type_impl( ) noexcept;
354
355 template<typename T, typename AllowRawString>
356 struct deduced_element {
357 using type =
358 typename decltype( json_deduced_type_impl<T,
359 AllowRawString>( ) )::type;
360 };
361
366 template<typename T, typename AllowRawString>
367 using deduced_element_t =
368 typename daw::conditional_t<AllowRawString::value,
369 daw::traits::identity<T>,
370 deduced_element<T, AllowRawString>>::type;
371
372 template<typename Tuple, typename AllowRawString,
373 typename = std::make_index_sequence<std::tuple_size_v<Tuple>>>
374 struct deduced_tuple_types;
375
376 template<typename Tuple, typename AllowRawString, std::size_t... Is>
377 struct deduced_tuple_types<Tuple, AllowRawString,
378 std::index_sequence<Is...>> {
379 using type = std::tuple<deduced_element_t<
380 daw::remove_cvref_t<std::tuple_element_t<Is, Tuple>>,
381 AllowRawString>...>;
382 };
383
386 template<typename Tuple, typename AllowRawString>
387 using deduced_tuple_types_t = typename daw::conditional_t<
388 AllowRawString::value, daw::traits::identity<use_default>,
389 deduced_tuple_types<Tuple, AllowRawString>>::type;
390
391 template<typename T, typename AllowRawString = std::true_type>
392 DAW_ATTRIB_INLINE DAW_CONSTEVAL auto json_link_quick_map( ) noexcept {
393 if constexpr( is_a_json_type_v<T> ) {
394 return json_link_quick_map_type<T>{ };
395 } else if constexpr( has_deduced_type_mapping_v<T, AllowRawString> ) {
396 using mapped_type_t = json_deduced_type_map<T, AllowRawString>;
397 using parse_type = daw::constant<mapped_type_t::parse_type>;
398 using is_null = daw::constant<mapped_type_t::is_null>;
399 if constexpr( parse_type::value == JsonParseTypes::Unknown ) {
400 if constexpr( is_null::value ) {
401 if constexpr( has_json_data_contract_trait_v<
402 typename mapped_type_t::sub_type> ) {
403 return json_link_quick_map_type<
404 json_base::json_class_null<T>>{ };
405 } else {
406 return json_link_quick_map_type<json_base::json_raw_null<T>>{ };
407 }
408 } else {
409 return json_link_quick_map_type<json_base::json_raw<T>>{ };
410 }
411 } else if constexpr( parse_type::value ==
412 JsonParseTypes::StringRaw ) {
413 if constexpr( is_null::value ) {
414 return json_link_quick_map_type<
415 json_base::json_string_raw_null<T>>{ };
416 } else {
417 return json_link_quick_map_type<json_base::json_string_raw<T>>{ };
418 }
419 } else if constexpr( parse_type::value ==
420 JsonParseTypes::StringEscaped ) {
421 if constexpr( is_null::value ) {
422 return json_link_quick_map_type<
423 json_base::json_string_null<T>>{ };
424 } else {
425 return json_link_quick_map_type<json_base::json_string<T>>{ };
426 }
427 } else if constexpr( parse_type::value ==
428 JsonParseTypes::StringInsitu ) {
429 if constexpr( is_null::value ) {
430 return json_link_quick_map_type<
431 json_base::json_string_insitu_null<T>>{ };
432 } else {
433 return json_link_quick_map_type<
434 json_base::json_string_insitu<T>>{ };
435 }
436 } else if constexpr( parse_type::value == JsonParseTypes::Bool ) {
437 if constexpr( is_null::value ) {
438 return json_link_quick_map_type<json_base::json_bool_null<T>>{ };
439 } else {
440 return json_link_quick_map_type<json_base::json_bool<T>>{ };
441 }
442 } else if constexpr( is_arithmetic_parse_type_v<parse_type::value> ) {
443 if constexpr( is_null::value ) {
444 return json_link_quick_map_type<
445 json_base::json_number_null<T>>{ };
446 } else {
447 return json_link_quick_map_type<json_base::json_number<T>>{ };
448 }
449 } else if constexpr( parse_type::value == JsonParseTypes::Tuple ) {
450 if constexpr( is_null::value ) {
451 using tp_t = json_details::unwrapped_t<T>;
452 return json_link_quick_map_type<json_base::json_tuple_null<
453 T,
454 deduced_tuple_types_t<tp_t, AllowRawString>>>{ };
455 } else {
456 return json_link_quick_map_type<json_base::json_tuple<
457 T,
458 deduced_tuple_types_t<T, AllowRawString>>>{ };
459 }
460 } else if constexpr( parse_type::value == JsonParseTypes::KeyValue ) {
461 if constexpr( is_null::value ) {
462 using b_t = typename mapped_type_t::type;
463 using k_t = deduced_element_t<typename b_t::key, AllowRawString>;
464 using v_t =
465 deduced_element_t<typename b_t::value, AllowRawString>;
466 return json_link_quick_map_type<
467 json_base::json_key_value_null<T, v_t, k_t>>{ };
468 } else {
469 using k_t =
470 deduced_element_t<typename mapped_type_t::key, AllowRawString>;
471 using v_t = deduced_element_t<typename mapped_type_t::value,
472 AllowRawString>;
473 return json_link_quick_map_type<
474 json_base::json_key_value<T, v_t, k_t>>{ };
475 }
476 } else if constexpr( parse_type::value == JsonParseTypes::Array ) {
477 if constexpr( is_null::value ) {
478 using b_t = typename mapped_type_t::type;
479 using v_t =
480 deduced_element_t<typename b_t::value, AllowRawString>;
481 return json_link_quick_map_type<json_base::json_nullable<
482 T,
483 json_base::json_array<v_t, json_details::unwrapped_t<T>>>>{ };
484 } else {
485 using v_t = deduced_element_t<typename mapped_type_t::value,
486 AllowRawString>;
487 return json_link_quick_map_type<json_base::json_array<v_t, T>>{ };
488 }
489#if defined( DAW_JSON_HAS_REFLECTION )
490 } else if constexpr( refl_details::PotentiallyReflectable<T> ) {
491 return json_link_quick_map_type<
492 json_base::json_reflected_class<T>>{ };
493#endif
494 } else {
495 return json_link_quick_map_type<void, false>{ };
496 }
497#if defined( DAW_JSON_HAS_REFLECTION )
498 } else if constexpr( refl_details::PotentiallyReflectable<T> ) {
499 return json_link_quick_map_type<
500 json_base::json_reflected_class<T>>{ };
501#endif
502 } else {
503 return json_link_quick_map_type<void, false>{ };
504 }
505 }
506
508 template<typename T, typename AllowRawString = std::true_type>
509 DAW_CPP20_CONCEPT has_json_link_quick_map_v =
510 decltype( json_link_quick_map<T, AllowRawString>( ) )::value;
511
513 template<typename T, typename AllowRawString = std::true_type>
514 using json_link_quick_map_t =
515 typename decltype( json_link_quick_map<
516 T, AllowRawString>( ) )::mapped_type;
517
518 template<typename JsonType>
519 struct json_class_map_type {
521 };
522
523 template<typename>
524 struct is_json_class_map : std::false_type {};
525
526 // This maybe specialized
527 template<typename T>
528 inline constexpr bool is_json_class_map_v =
529 has_json_data_contract_trait_v<T> and
530 is_json_class_map_v<json_data_contract_trait_t<T>>;
531
533 template<typename T>
534 inline constexpr bool is_char_pointer_v =
535 std::is_pointer_v<T> and
536 std::is_same_v<std::remove_cv_t<std::remove_pointer_t<T>>, char>;
537
539 template<typename T>
540 inline constexpr bool is_char_array_v =
541 std::rank_v<T> == 1 and
542 std::is_same_v<std::remove_cv_t<std::remove_extent_t<T>>, char>;
543
544 template<typename T, typename AllowRawString>
545 DAW_ATTRIB_INLINE DAW_CONSTEVAL auto json_deduced_type_impl( ) noexcept {
546 if constexpr( is_char_array_v<T> and not AllowRawString::value ) {
547 return daw::traits::identity<
548 json_base::json_string_insitu<daw::string_view>>{ };
549 } else if constexpr( is_a_basic_json_value<T> ) {
550 return daw::traits::identity<json_base::json_raw<T>>{ };
551#if defined( DAW_JSON_HAS_REFLECTION )
552 } else if constexpr( refl_details::HasTypeLevelAnnotation<T> ) {
553 return daw::traits::identity<
554 refl_details::type_annotation_mapping_t<T>>{ };
555#endif
556 } else if constexpr( is_an_ordered_member_v<T> ) {
557 using type = T;
558 return daw::traits::identity<type>{ };
559 } else if constexpr( has_json_data_contract_trait_v<T> ) {
560 static_assert( not std::is_same_v<T, void> );
561
562 using type = json_base::json_class<T>;
563
564 static_assert( not std::is_same_v<daw::remove_cvref_t<type>, void>,
565 "Detection failure" );
566 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
567 "Detection failure" );
568 return daw::traits::identity<type>{ };
569 } else if constexpr( has_json_link_quick_map_v<T, AllowRawString> ) {
570 static_assert( not std::is_same_v<T, void> );
571 using type = json_link_quick_map_t<T, AllowRawString>;
572 using rcvref_type = remove_cvref_t<type>;
573 static_assert( not std::is_same_v<rcvref_type, void>,
574 "Detection failure" );
575 static_assert( not is_nonesuch_v<rcvref_type>, "Detection failure" );
576 return daw::traits::identity<type>{ };
577 } else if constexpr( is_a_json_type_v<T> ) {
578 static_assert( not std::is_same_v<T, void> );
579 using type =
580 typename daw::conditional_t<is_json_class_map_v<T>,
581 json_class_map_type<T>,
582 daw::traits::identity<T>>::type;
583 static_assert( not std::is_same_v<daw::remove_cvref_t<type>, void>,
584 "Detection failure" );
585 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
586 "Detection failure" );
587 return daw::traits::identity<type>{ };
588 } else if constexpr( concepts::is_nullable_value_v<T> ) {
589 using value_type = concepts::nullable_value_type_t<T>;
590 using sub_type = typename decltype( json_deduced_type_impl<
591 value_type,
592 AllowRawString>( ) )::type;
593 using type = json_base::json_nullable<T, sub_type>;
594 return daw::traits::identity<type>{ };
595 } else if constexpr( concepts::is_container_v<T> ) {
596 using type = json_base::json_array<
597 deduced_element_t<typename T::value_type, AllowRawString>,
598 T>;
599 return daw::traits::identity<type>{ };
600 } else if constexpr( std::is_empty_v<T> and
601 std::is_default_constructible_v<T> ) {
602 // Allow empty/default constructible types to work without mapping
603 using type = json_details::json_empty_class<T>;
604 return daw::traits::identity<type>{ };
605#if not defined( DAW_JSON_HAS_REFLECTION )
606 } else if constexpr( can_convert_to_tuple_v<T> ) {
607 using type = json_base::json_tuple<T>;
608 return daw::traits::identity<type>{ };
609#endif
610 } else {
611 static_assert( daw::deduced_false_v<T>,
612 "Could not deduced data contract type and there is no "
613 "json_data_contract_specialization" );
614 }
615 }
616
617 template<typename T, typename AllowRawString = std::true_type>
618 using json_deduced_type = typename DAW_TYPEOF(
619 json_deduced_type_impl<T, AllowRawString>( ) )::type;
620
625 template<typename JsonClass, typename Value>
626 using json_serialize_deduced_type = typename daw::conditional_t<
627 std::is_same_v<use_default, JsonClass>,
628 ident_trait<json_deduced_type, Value, std::false_type>,
629 daw::conditional_t<
630 is_a_json_type_v<JsonClass>,
631 ident_trait<json_deduced_type, JsonClass>,
632 ident_trait<json_deduced_type, JsonClass, std::false_type>>>::type;
633
634 template<typename T, typename AllowRawString = std::true_type>
635 DAW_CPP20_CONCEPT has_json_deduced_type_v =
636 not std::is_same_v<json_deduced_type<T, AllowRawString>,
638
639 template<typename... Ts>
640 DAW_CPP20_CONCEPT all_have_deduced_type_v =
641 ( has_json_deduced_type_v<Ts> and ... );
642
643 template<typename JsonElement, typename Container, typename Constructor>
644 struct json_constructor<
645 json_base::json_array<JsonElement, Container, Constructor>> {
646 using json_element_t = json_deduced_type<JsonElement>;
647 using json_element_parse_to_t = json_result_t<json_element_t>;
648
649 using container_t =
650 daw::conditional_t<std::is_same_v<Container, use_default>,
651 std::vector<json_element_parse_to_t>, Container>;
652
653 using type =
654 daw::conditional_t<std::is_same_v<use_default, Constructor>,
656
657 static_assert(
658 daw::is_callable_v<type, json_element_parse_to_t const *,
659 json_element_parse_to_t const *>,
660 "Constructor must support copy and/or move construction" );
661 };
662
663 template<typename JsonElement, typename Container, typename Constructor>
664 struct json_result<
665 json_base::json_array<JsonElement, Container, Constructor>> {
666 using constructor_t = typename json_constructor<
667 json_base::json_array<JsonElement, Container, Constructor>>::type;
668 using json_element_t = json_deduced_type<JsonElement>;
669 using json_element_parse_to_t =
670 typename json_result<json_element_t>::type;
671 using type =
672 std::invoke_result_t<constructor_t, json_element_parse_to_t const *,
673 json_element_parse_to_t const *>;
674 };
675
676 template<typename T>
677 DAW_CPP20_CONCEPT has_unnamed_default_type_mapping_v =
678 has_json_deduced_type_v<T>;
679
680 template<typename JsonMember>
681 using from_json_result_t = json_result_t<json_deduced_type<JsonMember>>;
682
683 template<typename Constructor, typename... Members>
684 using json_class_parse_result_impl2 =
685 std::invoke_result_t<Constructor, json_result_t<Members>...>;
686
687 template<typename Constructor, typename... Members>
688 using json_class_parse_result_impl =
689 daw::detected_t<json_class_parse_result_impl2, Constructor, Members...>;
690
691 template<typename Constructor, typename... Members>
692 struct could_not_construct_from_members_error;
693
694 template<typename Constructor, typename... Members>
695 using json_class_parse_result_t = typename daw::conditional_t<
696 daw::is_callable_v<Constructor, json_result_t<Members>...>,
697 std::invoke_result<Constructor, json_result_t<Members>...>,
698 daw::traits::identity<could_not_construct_from_members_error<
699 Constructor, Members...>>>::type;
700
701 template<typename JsonMember>
702 using dependent_member_t = typename JsonMember::dependent_member;
703
704 template<typename JsonMember, typename = void>
705 inline constexpr bool has_dependent_member_v = false;
706
707 template<typename JsonMember>
708 inline constexpr bool has_dependent_member_v<
709 JsonMember, std::void_t<dependent_member_t<JsonMember>>> = true;
710
711 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_nullable_dependent_member_v,
712 T::member_type::dependent_member );
713
714 template<typename JsonMember>
715 DAW_REQUIRES( is_json_nullable_v<JsonMember> )
716 inline constexpr bool has_dependent_member_v<
717 JsonMember DAW_ENABLEIF_S( is_json_nullable_v<JsonMember> )> =
718 has_nullable_dependent_member_v<JsonMember>;
719
720 template<typename Constructor>
721 [[nodiscard]] DAW_ATTRIB_INLINE constexpr auto
722 construct_nullable_empty( ) {
723 if constexpr( daw::is_callable_v<
724 Constructor,
725 concepts::construct_nullable_with_empty_t> ) {
726 return Constructor{ }( concepts::construct_nullable_with_empty );
727 } else {
728 return Constructor{ }( );
729 }
730 }
731 } // namespace json_details
732 } // namespace DAW_JSON_VER
733} // namespace daw::json
DAW_REQUIRES(daw::json::json_details::is_container_opted_into_json_iostreams_v< Container >) std
An opt in ostream interface for containers of types that have JSON mappings.
#define DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT(Name,...)
#define DAW_JSON_MAKE_REQ_TRAIT(Name,...)
typename json_data_contract< T >::type json_data_contract_trait_t
This trait gets us the mapping type from the contract.
JsonParseTypes
The tags used by the parser to determine what parser to call.
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
Mapping class for JSON data structures to C++. It must be specialized in order to parse to a user cla...
This class is used as a way to indicate that a json_data_contract specialization has not been done fo...
Default Constructor for a type. It accounts for aggregate types and uses brace construction for them.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20