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
29#include <string>
30#include <string_view>
31#include <type_traits>
32
33namespace daw {
35 struct use_default;
36} // namespace daw
37
38/***
39 * Customization point traits
40 *
41 */
42namespace daw::json {
43 inline namespace DAW_JSON_VER {
44 namespace json_details {
45 template<template<typename...> typename Trait, typename... Params>
46 struct ident_trait {
47 using type = Trait<Params...>;
48 };
49
50 DAW_JSON_MAKE_REQ_TRAIT( has_op_bool_v,
51 static_cast<bool>( std::declval<T>( ) ) );
52
53 DAW_JSON_MAKE_REQ_TRAIT( has_op_star_v, *std::declval<T>( ) );
54
55 template<typename Constructor, typename... Args>
56 struct constructor_cannot_be_invoked;
57
58 template<typename Constructor, typename... Args>
59 struct construction_result
60 : daw::conditional_t<
61 daw::is_callable_v<Constructor, Args...>,
62 std::invoke_result<Constructor, Args...>,
63 daw::traits::identity<
64 constructor_cannot_be_invoked<Constructor, Args...>>> {};
65 } // namespace json_details
66
67 namespace json_details {
68 template<typename JsonMember>
69 using without_name = typename JsonMember::without_name;
70
71 template<typename JsonMember, JSONNAMETYPE NewName, bool Cond>
72 using copy_name_when = daw::conditional_t<
73 Cond, typename JsonMember::template with_name<NewName>, JsonMember>;
74
75 template<typename JsonMember, JSONNAMETYPE NewName>
76 using copy_name_when_noname =
77 copy_name_when<JsonMember, NewName, is_no_name_v<JsonMember>>;
78 } // namespace json_details
79
80 namespace json_details {
82 is_json_map_alias_v,
84
85 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_switcher_v, T::switcher );
86
88 force_aggregate_construction_test1,
90
91 DAW_JSON_MAKE_REQ_TRAIT( force_aggregate_construction_test2,
92 T::force_aggregate_construction );
93 } // namespace json_details
94 /***
95 * This trait can be specialized such that when class being returned has
96 * non-move/copyable members the construction can be done with { } instead
97 * of a callable. This is a blunt object and probably should not be used
98 * add a type alias named force_aggregate_construction to your
99 * json_data_contract specialization
100 * @tparam T type to specialize
101 */
102 template<typename T>
103 inline constexpr bool force_aggregate_construction_v =
104 json_details::force_aggregate_construction_test1<T> or
105 json_details::force_aggregate_construction_test2<T>;
106
107 namespace json_details {
108 template<typename, typename = void>
109 struct json_constructor;
110
111 template<typename T>
112 struct json_constructor<T, std::void_t<typename T::constructor_t>> {
113 using type = typename T::constructor_t;
114 };
115
116 template<typename T>
117 using json_constructor_t = typename json_constructor<T>::type;
118
119 template<typename, typename = void>
120 struct json_result;
121
122 template<typename T>
123 struct json_result<T, std::void_t<typename T::parse_to_t>> {
124 using type = typename T::parse_to_t;
125 };
126
127 template<typename T>
128 using json_result_t = typename json_result<T>::type;
129
130 template<typename, typename = void>
131 struct json_base_type;
132
133 template<typename T>
134 struct json_base_type<T, std::void_t<json_result_t<T>>> {
135 using type = json_result_t<T>;
136 };
137
138 template<typename T>
139 using json_base_type_t = typename json_base_type<T>::type;
140
142 is_default_default_constructor_type_v,
143 T::i_am_the_default_default_constructor_type );
144
145 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_stateless_allocator_v,
146 T::has_stateless_allocator );
147
149 has_data_contract_constructor_v, json_data_contract<T>::constructor_t );
150
151 template<typename>
152 inline constexpr bool must_be_class_member_v = false;
153 } // namespace json_details
154
155 template<typename Constructor, typename T, typename ParseState>
156 inline constexpr bool should_construct_explicitly_v =
157 not json_details::has_data_contract_constructor_v<T> and
158 ( force_aggregate_construction_v<T> or
159 json_details::is_default_default_constructor_type_v<Constructor> or
160 not json_details::has_stateless_allocator_v<ParseState> );
161
162 template<typename... Ts>
163 DAW_CPP20_CONCEPT is_empty_pack_v = sizeof...( Ts ) == 0;
164
171 template<typename>
172 inline constexpr bool can_single_allocation_string_v = false;
173
174 template<typename Char, typename CharTrait, typename Allocator>
175 inline constexpr bool can_single_allocation_string_v<
176 std::basic_string<Char, CharTrait, Allocator>> = true;
177
178 template<typename T>
180 std::bool_constant<can_single_allocation_string_v<T>>;
181
182 namespace json_details {
183 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_a_json_type_v,
184 T::i_am_a_json_type );
185
186 template<typename... Ts>
187 inline constexpr bool are_json_types_v = ( is_a_json_type_v<Ts> and ... );
188
191 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_an_ordered_member_v,
192 T::i_am_an_ordered_member );
193
194 template<typename T>
195 using is_an_ordered_member =
196 std::bool_constant<is_an_ordered_member_v<T>>;
197
198 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_a_json_tagged_variant_v,
199 T::i_am_a_json_tagged_variant );
200
201 template<typename T>
202 using json_class_constructor_t_impl =
204
205 template<typename T>
206 using data_contract_constructor_t =
208
209 template<typename T, typename Default>
210 using json_class_constructor_t = daw::detected_or_t<
211 typename daw::conditional_t<
212 std::is_same_v<use_default, Default>,
213 daw::conditional_t<has_data_contract_constructor_v<T>,
214 ident_trait<data_contract_constructor_t, T>,
215 ident_trait<default_constructor, T>>,
216 daw::traits::identity<Default>>::type,
217 json_class_constructor_t_impl, T>;
218
220 is_string_view_like_v, ( (void)( std::data( std::declval<T>( ) ) ),
221 (void)( std::size( std::declval<T>( ) ) ) ) );
222
223 static_assert( is_string_view_like_v<std::string_view> );
224
225 } // namespace json_details
226
227 /***
228 * Trait for passively exploiting the zero termination when the type
229 * guarantees it.
230 */
231 template<typename>
232 inline constexpr bool is_zero_terminated_string_v = false;
233
234 template<typename CharT, typename Traits, typename Alloc>
235 inline constexpr bool
236 is_zero_terminated_string_v<std::basic_string<CharT, Traits, Alloc>> =
237 true;
238
239 template<typename T>
241 std::bool_constant<is_zero_terminated_string_v<T>>;
242
243 namespace json_details {
244 template<typename ParsePolicy, auto Option>
245 using apply_policy_option_t =
246 typename ParsePolicy::template SetPolicyOptions<Option>;
247
248 template<typename ParsePolicy, typename String, auto Option>
249 using apply_zstring_policy_option_t = daw::conditional_t<
250 is_zero_terminated_string_v<daw::remove_cvref_t<String>>,
251 apply_policy_option_t<ParsePolicy, Option>, ParsePolicy>;
252
253 template<typename String>
254 inline constexpr bool is_mutable_string_v =
255 not std::is_const_v<std::remove_pointer_t<std::remove_reference_t<
256 decltype( std::data( std::declval<String &&>( ) ) )>>>;
257
258 /*
259 template<typename ParsePolicy, typename String, auto OptionMutable,
260 auto OptionImmutable>
261 using apply_mutable_policy = daw::conditional_t<
262 ParsePolicy::allow_temporarily_mutating_buffer( ),
263 daw::conditional_t<is_mutable_string_v<String>,
264 apply_policy_option_t<ParsePolicy, OptionMutable>,
265 apply_policy_option_t<ParsePolicy, OptionImmutable>>,
266 daw::conditional_t<
267 (is_rvalue_string<String> and is_mutable_string_v<String>),
268 apply_policy_option_t<ParsePolicy, OptionMutable>,
269 apply_policy_option_t<ParsePolicy, OptionImmutable>>>;
270 */
271 } // namespace json_details
272
273 /***
274 * Ignore unknown members trait allows the parser to skip unknown members
275 * when the default is exact
276 * Set to true when data contract has type alias ignore_unknown_members
277 */
279 ignore_unknown_members_v, json_data_contract<T>::ignore_unknown_members );
280
281 /***
282 * A trait to specify that this class, when parsed, will describe all
283 * members of the JSON object. Anything not mapped is an error.
284 * Either specialize this variable daw::json::is_exact_class_mapping_v, or
285 * have a type in your json_data_contract named exact_class_mapping for your
286 * type
287 */
289 is_exact_class_mapping_v, json_data_contract<T>::exact_class_mapping );
290
291 namespace json_details {
292 template<typename T, typename ParseState>
293 DAW_CPP20_CONCEPT all_json_members_must_exist_v =
294 not ignore_unknown_members_v<T> and
295 ( is_exact_class_mapping_v<T> or
296 ParseState::use_exact_mappings_by_default );
297
298 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( has_element_type, T::element_type );
299
300 template<template<typename...> typename T, typename... Params>
301 struct identity_parts {
302 using type = T<Params...>;
303 };
304 } // namespace json_details
305
306 /***
307 * is_pointer_like is used in json_array to ensure that to_json_data returns
308 * a Container/View of the data with the size encoded with it.
309 * The std
310 */
311 template<typename T>
312 inline constexpr bool is_pointer_like_v =
313 std::is_pointer_v<T> or json_details::has_element_type<T>;
314
317 template<typename Tuple, typename = void>
319
320 template<typename... Ts>
321 struct tuple_elements_pack<std::tuple<Ts...>> {
322 using type = std::tuple<Ts...>;
323
324 static constexpr auto size = sizeof...( Ts );
325
326 template<std::size_t Idx>
327 using element_t = std::tuple_element_t<Idx, type>;
328
329 template<std::size_t Idx, typename Tuple>
330 static constexpr decltype( auto ) get( Tuple &&tp ) {
331 return std::get<Idx>( DAW_FWD( tp ) );
332 }
333 };
334
335 template<typename... Ts>
336 struct tuple_elements_pack<daw::fwd_pack<Ts...>> {
337 using type = daw::fwd_pack<Ts...>;
338
339 static constexpr auto size = sizeof...( Ts );
340
341 template<std::size_t Idx>
342 using element_t =
343 daw::remove_cvref_t<typename std::tuple_element_t<Idx, type>>;
344
345 template<std::size_t Idx, typename Tuple>
346 static constexpr decltype( auto ) get( Tuple &&tp ) {
347 return DAW_FWD( tp ).template get<Idx>( );
348 }
349 };
350
356 template<typename T>
357 inline constexpr bool is_pinned_type_v = not(
358 (std::is_copy_constructible_v<T> and std::is_copy_assignable_v<T>) or
359 ( std::is_move_constructible_v<T> and std::is_move_assignable_v<T> ) );
360
361 namespace json_details {
362 template<typename, typename = void>
363 inline constexpr bool is_tuple_v = false;
364
365 template<typename... Ts>
366 inline constexpr bool is_tuple_v<std::tuple<Ts...>> = true;
367
368 template<typename T>
369 inline constexpr bool
370 is_tuple_v<T, typename tuple_elements_pack<T>::type> = true;
371
372 template<typename T>
373 using unwrapped_t = concepts::nullable_value_type_t<T>;
374
375 template<typename T>
376 using mapped_type_t = typename T::mapped_type;
377
378 template<typename T>
379 using key_type_t = typename T::key_type;
380
381 // DAW disabling to fix #357
382#if true or defined( DAW_JSON_DISABLE_RANDOM )
383 template<bool>
384 DAW_CPP20_CONCEPT can_be_random_iterator_v = false;
385#else
386 template<bool IsKnown>
387 DAW_CPP20_CONCEPT can_be_random_iterator_v = IsKnown;
388#endif
389
390 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_literal_json_type_v,
391 T::as_string );
392
393 template<typename JsonMember>
394 using literal_json_type_as_string = typename JsonMember::as_string;
395
396 DAW_JSON_MAKE_REQ_TYPE_ALIAS_TRAIT( is_deduced_empty_class_v,
397 T::i_am_a_deduced_empty_class );
398 } // namespace json_details
399 } // namespace DAW_JSON_VER
400} // 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