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