21 #include <daw/daw_consteval.h>
22 #include <daw/daw_constinit.h>
23 #include <daw/daw_likely.h>
24 #include <daw/daw_traits.h>
27 #include <type_traits>
31 namespace json_details {
45 template<
typename JsonMember,
typename ParseState>
46 [[nodiscard]] DAW_ATTRIB_INLINE
static constexpr json_result_t<JsonMember>
47 parse_ordered_class_member( std::size_t &member_index,
48 ParseState &parse_state ) {
50 using json_member_t = ordered_member_subtype_t<JsonMember>;
52 parse_state.move_next_member_or_end( );
57 if constexpr( is_an_ordered_member_v<JsonMember> ) {
58 pocm_details::maybe_skip_members<is_json_nullable_v<json_member_t>>(
59 parse_state, member_index, JsonMember::member_index );
62 ErrorReason::UnexpectedEndOfData, parse_state );
68 if( DAW_UNLIKELY( parse_state.front( ) ==
']' ) ) {
69 if constexpr( is_json_nullable_v<json_member_t> ) {
71 auto loc = ParseState{ };
72 return parse_value<json_member_t,
true,
73 json_member_t::expected_type>( loc );
79 return parse_value<json_member_t, false, json_member_t::expected_type>(
93 template<std::size_t member_position,
typename JsonMember,
94 AllMembersMustExist must_exist,
bool NeedsClassPositions,
95 typename ParseState, std::size_t N,
typename CharT,
bool B>
96 [[nodiscard]] DAW_ATTRIB_FLATINLINE
static constexpr json_result_t<
98 parse_class_member( ParseState &parse_state,
99 locations_info_t<N, CharT, B> &locations ) {
100 parse_state.move_next_member_or_end( );
103 not parse_state.empty( ) and parse_state.is_at_next_class_member( ),
104 ErrorReason::MissingMemberNameOrEndOfClass, parse_state );
106 auto [loc, known] = find_class_member<member_position, must_exist>(
107 parse_state, locations, is_json_nullable_v<JsonMember>,
112 if constexpr( NeedsClassPositions ) {
113 auto const cf = parse_state.class_first;
114 auto const cl = parse_state.class_last;
116 json_result_t<without_name<JsonMember>>> ) {
117 auto const after_parse = daw::on_scope_exit( [&] {
118 parse_state.class_first = cf;
119 parse_state.class_last = cl;
121 return parse_value<without_name<JsonMember>,
false,
122 JsonMember::expected_type>( parse_state );
125 parse_value<without_name<JsonMember>,
false,
126 JsonMember::expected_type>( parse_state );
127 parse_state.class_first = cf;
128 parse_state.class_last = cl;
132 return parse_value<without_name<JsonMember>,
false,
133 JsonMember::expected_type>( parse_state );
137 if( loc.is_null( ) ) {
138 if constexpr( is_json_nullable_v<JsonMember> ) {
139 return parse_value_null<without_name<JsonMember>,
true>( loc );
142 std::data( JsonMember::name ),
143 std::size( JsonMember::name ) ) ),
149 return parse_value<without_name<JsonMember>,
true,
150 JsonMember::expected_type>( loc );
153 template<
bool IsExactClass,
typename ParseState,
typename OldClassPos>
154 DAW_ATTRIB_INLINE
static constexpr
void
155 class_cleanup_now( ParseState &parse_state,
156 OldClassPos
const &old_class_pos ) {
158 ErrorReason::UnexpectedEndOfData, parse_state );
159 parse_state.move_next_member_or_end( );
161 parse_state.move_to_next_class_member( );
162 if constexpr( IsExactClass ) {
164 ErrorReason::UnknownMember, parse_state );
165 parse_state.remove_prefix( );
167 (void)parse_state.skip_class( );
171 parse_state.trim_left_checked( );
172 parse_state.set_class_position( old_class_pos );
182 template<
typename JsonClass,
typename... JsonMembers,
typename ParseState,
184 [[nodiscard]] DAW_ATTRIB_INLINE constexpr json_result_t<JsonClass>
185 parse_json_class( ParseState &parse_state, std::index_sequence<Is...> ) {
186 static_assert( is_a_json_type_v<JsonClass> );
187 using T = json_result_t<JsonClass>;
188 using Constructor = json_constructor_t<JsonClass>;
189 static_assert( has_json_data_contract_trait_v<T>,
"Unexpected type" );
191 daw::constant<( all_json_members_must_exist_v<T, ParseState>
192 ? AllMembersMustExist::yes
193 : AllMembersMustExist::no )>;
195 parse_state.trim_left( );
198 ErrorReason::InvalidClassStart, parse_state );
200 auto const old_class_pos = parse_state.get_class_position( );
201 parse_state.set_class_position( );
202 parse_state.remove_prefix( );
203 parse_state.trim_left( );
205 if constexpr(
sizeof...( JsonMembers ) == 0 ) {
207 class_cleanup_now<all_json_members_must_exist_v<T, ParseState>>(
208 parse_state, old_class_pos );
214 return construct_value_tp<T, Constructor>( parse_state,
218 using NeedClassPositions = std::bool_constant<(
219 ( must_be_class_member_v<typename JsonMembers::without_name> or
222 #if defined( DAW_JSON_BUGFIX_MSVC_KNOWN_LOC_ICE_003 )
223 auto known_locations =
224 make_locations_info<ParseState, JsonMembers...>( );
226 auto known_locations = DAW_AS_CONSTANT(
227 ( make_locations_info<ParseState, JsonMembers...>( ) ) );
234 auto const run_after_parse = daw::on_exit_success( [&] {
235 class_cleanup_now<all_json_members_must_exist_v<T, ParseState>>(
236 parse_state, old_class_pos );
238 (void)run_after_parse;
242 return T{ parse_class_member<
243 Is, daw::traits::nth_type<Is, JsonMembers...>,
244 must_exist::value, NeedClassPositions::value>(
245 parse_state, known_locations )... };
247 return construct_value_tp<T, Constructor>(
248 parse_state, fwd_pack{ parse_class_member<
249 Is, daw::traits::nth_type<Is, JsonMembers...>,
250 must_exist::value, NeedClassPositions::value>(
251 parse_state, known_locations )... } );
256 auto result = T{ parse_class_member<
257 Is, daw::traits::nth_type<Is, JsonMembers...>,
258 must_exist::value, NeedClassPositions::value>(
259 parse_state, known_locations )... };
261 class_cleanup_now<all_json_members_must_exist_v<T, ParseState>>(
262 parse_state, old_class_pos );
265 auto result = construct_value_tp<T, Constructor>(
266 parse_state, fwd_pack{ parse_class_member<
267 Is, daw::traits::nth_type<Is, JsonMembers...>,
268 must_exist::value, NeedClassPositions::value>(
269 parse_state, known_locations )... } );
271 class_cleanup_now<all_json_members_must_exist_v<T, ParseState>>(
272 parse_state, old_class_pos );
284 template<
typename JsonClass,
typename... JsonMembers,
typename ParseState>
285 [[nodiscard]]
static inline constexpr json_result_t<JsonClass>
286 parse_json_tuple_class( ParseState &parse_state ) {
287 static_assert( is_a_json_type_v<JsonClass> );
288 using T = json_base_type_t<JsonClass>;
289 using Constructor = json_constructor_t<JsonClass>;
290 static_assert( has_json_data_contract_trait_v<T>,
"Unexpected type" );
292 std::is_invocable_v<Constructor, json_result_t<JsonMembers>...>,
293 "Supplied types cannot be used for construction of this type" );
295 parse_state.trim_left( );
297 ErrorReason::InvalidArrayStart, parse_state );
298 auto const old_class_pos = parse_state.get_class_position( );
299 parse_state.set_class_position( );
300 parse_state.remove_prefix( );
301 parse_state.trim_left( );
303 std::size_t current_idx = 0;
306 auto const run_after_parse = daw::on_exit_success( [&] {
307 ordered_class_cleanup<all_json_members_must_exist_v<T, ParseState>,
308 ParseState, decltype( old_class_pos )>(
309 parse_state, old_class_pos );
311 (void)run_after_parse;
314 return T{ parse_ordered_class_member<JsonMembers>(
315 current_idx, parse_state )... };
317 return construct_value_tp<T, Constructor>(
318 parse_state, fwd_pack{ parse_ordered_class_member<JsonMembers>(
319 current_idx, parse_state )... } );
325 return T{ parse_ordered_class_member<JsonMembers>(
326 current_idx, parse_state )... };
328 return construct_value_tp<T, Constructor>(
329 parse_state, fwd_pack{ parse_ordered_class_member<JsonMembers>(
330 current_idx, parse_state )... } );
333 if constexpr( all_json_members_must_exist_v<T, ParseState> ) {
334 parse_state.trim_left( );
336 ErrorReason::UnknownMember, parse_state );
337 parse_state.remove_prefix( );
338 parse_state.trim_left( );
340 (void)parse_state.skip_array( );
342 parse_state.set_class_position( old_class_pos );
#define daw_json_assert_weak(Bool,...)
Assert that Bool is true when in Checked Input mode If false pass rest of args to daw_json_error.
DAW_ATTRIB_NOINLINE void daw_json_error(ErrorReason reason)
constexpr bool is_pinned_type_v
Is the type pinned in memory and unable to be copied/moved after construction(e.g....
constexpr bool should_construct_explicitly_v
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.