DAW JSON Link
Loading...
Searching...
No Matches
daw_json_traits.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
21
22#include <daw/cpp_17.h>
23#include <daw/daw_callable.h>
24#include <daw/daw_cpp20_concept.h>
25#include <daw/daw_fwd_pack_apply.h>
26#include <daw/daw_move.h>
27#include <daw/daw_traits.h>
28#include <daw/impl/daw_make_trait.h>
29
30#include <string>
31#include <string_view>
32#include <type_traits>
33
34namespace daw {
36 struct use_default;
37} // namespace daw
38
39/***
40 * Customization point traits
41 *
42 */
43namespace daw::json {
44 inline namespace DAW_JSON_VER {
45 namespace json_details {
46 template<template<typename...> typename Trait, typename... Params>
47 struct ident_trait {
48 using type = Trait<Params...>;
49 };
50
51 DAW_JSON_MAKE_REQ_TRAIT( has_op_bool_v,
52 static_cast<bool>( std::declval<T>( ) ) );
53
54 DAW_JSON_MAKE_REQ_TRAIT( has_op_star_v, *std::declval<T>( ) );
55
56 template<typename Constructor, typename... Args>
57 struct constructor_cannot_be_invoked;
58
59 template<typename Constructor, typename... Args>
60 struct construction_result
61 : daw::conditional_t<
62 daw::is_callable_v<Constructor, Args...>,
63 std::invoke_result<Constructor, Args...>,
64 daw::traits::identity<
65 constructor_cannot_be_invoked<Constructor, Args...>>> {};
66 } // namespace json_details
67
68 namespace json_details {
69 template<typename JsonMember>
70 using without_name = typename JsonMember::without_name;
71
72 template<typename JsonMember, JSONNAMETYPE NewName, bool Cond>
73 using copy_name_when = daw::conditional_t<
74 Cond, typename JsonMember::template with_name<NewName>, JsonMember>;
75
76 template<typename JsonMember, JSONNAMETYPE NewName>
77 using copy_name_when_noname =
78 copy_name_when<JsonMember, NewName, is_no_name_v<JsonMember>>;
79 } // namespace json_details
80
81 namespace json_details {
83 is_json_map_alias_v,
85
86 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_switcher_v, T::switcher );
87
89 force_aggregate_construction_test1,
91
92 DAW_JSON_MAKE_REQ_TRAIT( force_aggregate_construction_test2,
93 T::force_aggregate_construction );
94 } // namespace json_details
95 /***
96 * This trait can be specialized such that when class being returned has
97 * non-move/copyable members the construction can be done with { } instead
98 * of a callable. This is a blunt object and probably should not be used
99 * add a type alias named force_aggregate_construction to your
100 * json_data_contract specialization
101 * @tparam T type to specialize
102 */
103 template<typename T>
104 inline constexpr bool force_aggregate_construction_v =
105 json_details::force_aggregate_construction_test1<T> or
106 json_details::force_aggregate_construction_test2<T>;
107
108 namespace json_details {
109 template<typename, typename = void>
110 struct json_constructor;
111
112 template<typename T>
113 struct json_constructor<T, std::void_t<typename T::constructor_t>> {
114 using type = typename T::constructor_t;
115 };
116
117 template<typename T>
118 using json_constructor_t = typename json_constructor<T>::type;
119
120 template<typename, typename = void>
121 struct json_result;
122
123 template<typename T>
124 struct json_result<T, std::void_t<typename T::parse_to_t>> {
125 using type = typename T::parse_to_t;
126 };
127
128 template<typename T>
129 using json_result_t = typename json_result<T>::type;
130
131 template<typename, typename = void>
132 struct json_base_type;
133
134 template<typename T>
135 struct json_base_type<T, std::void_t<json_result_t<T>>> {
136 using type = json_result_t<T>;
137 };
138
139 template<typename T>
140 using json_base_type_t = typename json_base_type<T>::type;
141
143 is_default_default_constructor_type_v,
144 T::i_am_the_default_default_constructor_type );
145
146 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_stateless_allocator_v,
147 T::has_stateless_allocator );
148
150 has_data_contract_constructor_v, json_data_contract<T>::constructor_t );
151
152 template<typename>
153 inline constexpr bool must_be_class_member_v = false;
154 } // namespace json_details
155
156 template<typename Constructor, typename T, typename ParseState>
157 inline constexpr bool should_construct_explicitly_v =
158 not json_details::has_data_contract_constructor_v<T> and
159 ( force_aggregate_construction_v<T> or
160 json_details::is_default_default_constructor_type_v<Constructor> or
161 not json_details::has_stateless_allocator_v<ParseState> );
162
163 template<typename... Ts>
164 DAW_CPP20_CONCEPT is_empty_pack_v = sizeof...( Ts ) == 0;
165
172 template<typename>
173 inline constexpr bool can_single_allocation_string_v = false;
174
175 template<typename Char, typename CharTrait, typename Allocator>
176 inline constexpr bool can_single_allocation_string_v<
177 std::basic_string<Char, CharTrait, Allocator>> = true;
178
179 template<typename T>
181 std::bool_constant<can_single_allocation_string_v<T>>;
182
183 namespace json_details {
184 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_a_json_type_v,
185 T::i_am_a_json_type );
186
187 template<typename... Ts>
188 inline constexpr bool are_json_types_v = ( is_a_json_type_v<Ts> and ... );
189
192 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_an_ordered_member_v,
193 T::i_am_an_ordered_member );
194
195 template<typename T>
196 using is_an_ordered_member =
197 std::bool_constant<is_an_ordered_member_v<T>>;
198
199 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_a_json_tagged_variant_v,
200 T::i_am_a_json_tagged_variant );
201
202 template<typename T>
203 using json_class_constructor_t_impl =
205
206 template<typename T>
207 using data_contract_constructor_t =
209
210 template<typename T, typename Default>
211 using json_class_constructor_t = daw::detected_or_t<
212 typename daw::conditional_t<
213 std::is_same_v<use_default, Default>,
214 daw::conditional_t<has_data_contract_constructor_v<T>,
215 ident_trait<data_contract_constructor_t, T>,
216 ident_trait<default_constructor, T>>,
217 daw::traits::identity<Default>>::type,
218 json_class_constructor_t_impl, T>;
219
221 is_string_view_like_v, ( (void)( std::data( std::declval<T>( ) ) ),
222 (void)( std::size( std::declval<T>( ) ) ) ) );
223
224 static_assert( is_string_view_like_v<std::string_view> );
225
226 } // namespace json_details
227
228 /***
229 * Trait for passively exploiting the zero termination when the type
230 * guarantees it.
231 */
232 template<typename>
233 inline constexpr bool is_zero_terminated_string_v = false;
234
235 template<typename CharT, typename Traits, typename Alloc>
236 inline constexpr bool
237 is_zero_terminated_string_v<std::basic_string<CharT, Traits, Alloc>> =
238 true;
239
240 template<typename T>
242 std::bool_constant<is_zero_terminated_string_v<T>>;
243
244 namespace json_details {
245 template<typename ParsePolicy, auto Option>
246 using apply_policy_option_t =
247 typename ParsePolicy::template SetPolicyOptions<Option>;
248
249 template<typename ParsePolicy, typename String, auto Option>
250 using apply_zstring_policy_option_t = daw::conditional_t<
251 is_zero_terminated_string_v<daw::remove_cvref_t<String>>,
252 apply_policy_option_t<ParsePolicy, Option>, ParsePolicy>;
253
254 template<typename String>
255 inline constexpr bool is_mutable_string_v =
256 not std::is_const_v<std::remove_pointer_t<std::remove_reference_t<
257 decltype( std::data( std::declval<String &&>( ) ) )>>>;
258
259 /*
260 template<typename ParsePolicy, typename String, auto OptionMutable,
261 auto OptionImmutable>
262 using apply_mutable_policy = daw::conditional_t<
263 ParsePolicy::allow_temporarily_mutating_buffer( ),
264 daw::conditional_t<is_mutable_string_v<String>,
265 apply_policy_option_t<ParsePolicy, OptionMutable>,
266 apply_policy_option_t<ParsePolicy, OptionImmutable>>,
267 daw::conditional_t<
268 (is_rvalue_string<String> and is_mutable_string_v<String>),
269 apply_policy_option_t<ParsePolicy, OptionMutable>,
270 apply_policy_option_t<ParsePolicy, OptionImmutable>>>;
271 */
272 } // namespace json_details
273
274 /***
275 * Ignore unknown members trait allows the parser to skip unknown members
276 * when the default is exact
277 * Set to true when data contract has type alias ignore_unknown_members
278 */
280 ignore_unknown_members_v, json_data_contract<T>::ignore_unknown_members );
281
282 /***
283 * A trait to specify that this class, when parsed, will describe all
284 * members of the JSON object. Anything not mapped is an error.
285 * Either specialize this variable daw::json::is_exact_class_mapping_v, or
286 * have a type in your json_data_contract named exact_class_mapping for your
287 * type
288 */
290 is_exact_class_mapping_v, json_data_contract<T>::exact_class_mapping );
291
292 namespace json_details {
293 template<typename T, typename ParseState>
294 DAW_CPP20_CONCEPT all_json_members_must_exist_v =
295 not ignore_unknown_members_v<T> and
296 ( is_exact_class_mapping_v<T> or
297 ParseState::use_exact_mappings_by_default );
298
299 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_element_type, T::element_type );
300
301 template<template<typename...> typename T, typename... Params>
302 struct identity_parts {
303 using type = T<Params...>;
304 };
305 } // namespace json_details
306
307 /***
308 * is_pointer_like is used in json_array to ensure that to_json_data returns
309 * a Container/View of the data with the size encoded with it.
310 * The std
311 */
312 template<typename T>
313 inline constexpr bool is_pointer_like_v =
314 std::is_pointer_v<T> or json_details::has_element_type<T>;
315
318 template<typename Tuple, typename = void>
320
321 template<typename... Ts>
322 struct tuple_elements_pack<std::tuple<Ts...>> {
323 using type = std::tuple<Ts...>;
324
325 static constexpr auto size = sizeof...( Ts );
326
327 template<std::size_t Idx>
328 using element_t = std::tuple_element_t<Idx, type>;
329
330 template<std::size_t Idx, typename Tuple>
331 static constexpr decltype( auto ) get( Tuple &&tp ) {
332 return std::get<Idx>( DAW_FWD( tp ) );
333 }
334 };
335
336 template<typename... Ts>
337 struct tuple_elements_pack<daw::fwd_pack<Ts...>> {
338 using type = daw::fwd_pack<Ts...>;
339
340 static constexpr auto size = sizeof...( Ts );
341
342 template<std::size_t Idx>
343 using element_t =
344 daw::remove_cvref_t<typename std::tuple_element_t<Idx, type>>;
345
346 template<std::size_t Idx, typename Tuple>
347 static constexpr decltype( auto ) get( Tuple &&tp ) {
348 return DAW_FWD( tp ).template get<Idx>( );
349 }
350 };
351
357 template<typename T>
358 inline constexpr bool is_pinned_type_v = not(
359 (std::is_copy_constructible_v<T> and std::is_copy_assignable_v<T>) or
360 ( std::is_move_constructible_v<T> and std::is_move_assignable_v<T> ) );
361
362 namespace json_details {
363 template<typename, typename = void>
364 inline constexpr bool is_tuple_v = false;
365
366 template<typename... Ts>
367 inline constexpr bool is_tuple_v<std::tuple<Ts...>> = true;
368
369 template<typename T>
370 inline constexpr bool
371 is_tuple_v<T, typename tuple_elements_pack<T>::type> = true;
372
373 template<typename T>
374 using unwrapped_t = concepts::nullable_value_type_t<T>;
375
376 template<typename T>
377 using mapped_type_t = typename T::mapped_type;
378
379 template<typename T>
380 using key_type_t = typename T::key_type;
381
382 // DAW disabling to fix #357
383#if true or defined( DAW_JSON_DISABLE_RANDOM )
384 template<bool>
385 DAW_CPP20_CONCEPT can_be_random_iterator_v = false;
386#else
387 template<bool IsKnown>
388 DAW_CPP20_CONCEPT can_be_random_iterator_v = IsKnown;
389#endif
390
391 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_literal_json_type_v,
392 T::as_string );
393
394 template<typename JsonMember>
395 using literal_json_type_as_string = typename JsonMember::as_string;
396
397 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_deduced_empty_class_v,
398 T::i_am_a_deduced_empty_class );
399
400 template<typename T>
401 struct ensure_mapped {
402 static_assert( is_a_json_type_v<T>,
403 "The supplied type does not have a json_data_contract" );
404 using type = T;
405 };
406
407 template<typename T>
408 using ensure_mapped_t = typename ensure_mapped<T>::type;
409
410 DAW_MAKE_REQ_TRAIT_TYPE( is_json_member_list_v,
411 T::i_am_a_json_member_list );
412
413 template<typename T>
414 using ordered_member_subtype_test = typename T::json_member;
415
416 template<typename T>
417 using ordered_member_subtype_t =
418 typename daw::detected_or_t<T, ordered_member_subtype_test, T>;
419
420 template<typename T, typename Default>
421 inline constexpr auto json_class_constructor =
422 json_class_constructor_t<T, Default>{ };
423
424 template<typename T>
425 using json_nullable_member_type_t = typename T::member_type;
426 } // namespace json_details
427 } // namespace DAW_JSON_VER
428} // namespace daw::json
#define DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT(Name,...)
#define DAW_JSON_MAKE_REQ_TRAIT(Name,...)
#define DAW_JSON_MAKE_REQ_TRAIT_CUSTOM(Name,...)
Disable concepts on gcc < 13.3. See https://github.com/beached/daw_json_link/issues/454.
#define DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT_CUSTOM(Name, ...)
typename json_data_contract< T >::type json_data_contract_trait_t
This trait gets us the mapping type from the contract.
constexpr bool can_single_allocation_string_v
Can use the fast, pseudo random string iterators. They are InputIterators with an operator- that allo...
constexpr bool is_pinned_type_v
Is the type pinned in memory and unable to be copied/moved after construction(e.g....
std::bool_constant< is_zero_terminated_string_v< T > > is_zero_terminated_string
std::bool_constant< can_single_allocation_string_v< T > > can_single_allocation_string
Customization point traits.
Mapping class for JSON data structures to C++. It must be specialized in order to parse to a user cla...
daw::remove_cvref_t< typename std::tuple_element_t< Idx, type > > element_t
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20