15#if defined( DAW_JSON_HAS_REFLECTION )
19#include <daw/daw_bind_args_at.h>
20#include <daw/daw_concepts.h>
21#include <daw/daw_move.h>
22#include <daw/daw_pipelines.h>
34 struct refl_ignored_value : refl_annotation_base, refl_ignored_base {
37 explicit constexpr refl_ignored_value( D value )
38 : default_value( value ) {}
41 constexpr operator T( )
const {
42 if constexpr( std::is_convertible_v<D, T> ) {
44 }
else if constexpr(
requires( D v ) {
45 { v( ) } -> std::convertible_to<T>;
47 return default_value( );
52 struct refl_ignored : refl_annotation_base, refl_ignored_base {
53 explicit consteval refl_ignored( ) =
default;
56 static consteval auto operator( )( T &&rhs ) {
57 return refl_ignored_value<T>{ DAW_FWD( rhs ) };
61 consteval operator T( )
const {
66 struct member_reflection_t {};
68 template<
typename T, std::
size_t Idx>
69 using submember_type_t = std::tuple_element_t<Idx, to_tuple_t<T>>;
72 constexpr E enum_from_string( std::string_view name ) {
73 static constexpr auto enums =
74 reflect_constant_array( enumerators_of( ^^E ) );
75 template for(
constexpr auto enumerator : [:enums:] ) {
77 if( name == identifier_of( enumerator ) ) {
78 return [:enumerator:];
85 constexpr std::string_view enum_to_string( E value ) {
86 static constexpr auto enums =
87 reflect_constant_array( enumerators_of( ^^E ) );
88 template for(
constexpr auto enumerator : [:enums:] ) {
89 if( value == [:enumerator:] ) {
90 return identifier_of( enumerator );
93 daw_json_error(
true, ErrorReason::CouldNotFindEnumeratorForValue );
94 return std::string_view{ };
98 struct reflect_enum_as_string {
99 static constexpr E operator( )( std::string_view name ) {
100 return enum_from_string<E>( name );
103 static constexpr std::string_view operator( )( E value ) {
104 return enum_to_string( value );
110 template<EnumType E, json_options_t NumberOptions>
111 struct reflect_enum_as_string_or_number {
112 using number_t = std::underlying_type_t<E>;
113 using json_number_t = json_number_no_name<number_t, NumberOptions>;
117 static constexpr E operator( )( std::string_view
json_value ) {
119 ErrorReason::UnexpectedEndOfData );
121 auto const name_end =
json_value.find(
'"', 1 );
123 ErrorReason::InvalidString );
124 auto const name =
json_value.substr( 1, name_end - 1 );
128 not( name.front( ) ==
'-' or name.front( ) ==
'+' or
129 ( name.front( ) >=
'0' and name.front( ) <=
'9' ) ) ) {
130 return enum_from_string<E>( name );
133 return static_cast<E
>( from_json<json_number_t>( json_value ) );
136 template<
typename WritableType>
137 static constexpr WritableType operator( )( WritableType it, E value ) {
138 static constexpr auto enums =
139 reflect_constant_array( enumerators_of( ^^E ) );
140 template for(
constexpr auto enumerator : [:enums:] ) {
141 if( value == [:enumerator:] ) {
142 static constexpr std::string_view name = identifier_of( enumerator );
149 return json_details::member_to_string<json_number_t>(
150 std::move( it ),
static_cast<number_t
>( value ) );
154 template<
typename T, std::size_t... Idx>
155 consteval std::meta::info
156 get_json_members_list_impl( std::index_sequence<Idx...> ) {
157 return ^^json_member_list<get_member_link_t<T, Idx>...>;
161 consteval std::meta::info get_json_member_list( ) {
162 static constexpr auto sz =
163 get_non_ignored_reflectible_members<T>( ).size( );
164 return get_json_members_list_impl<T>( std::make_index_sequence<sz>{ } );
167 template<EnumType E, json_options_t Options>
169 reflect_enum_as_string<E>, Options> {
172 template<EnumType E, json_options_t NumberOptions>
173 struct enum_string_or_number
175 E, reflect_enum_as_string_or_number<E, NumberOptions>,
176 reflect_enum_as_string_or_number<E, NumberOptions>,
177 options::json_custom_opt( options::JsonCustomTypes::Any )> {};
179 template<Reflectable T>
180 consteval bool has_reflected_submembers( ) {
181 static constexpr auto members = [:as_stdarray(
182 get_reflectible_members<T>( ) ):];
183 template for(
constexpr auto member : members ) {
184 if( not annotations_of_with_base_type( member, ^^refl_annotation_base )
198 struct reflect_base_t {
202 template<json_name Name>
203 static constexpr auto rename = refl_details::refl_rename{ Name.m_data };
205 template<
typename JsonMember>
206 static constexpr auto map_as = refl_details::refl_map_as{ ^^JsonMember };
211 static constexpr auto ignored = refl_details::refl_ignored{ };
214 template<json_options_t Options>
215 static constexpr auto enum_string_with_options =
216 refl_details::refl_enum_string{ Options };
218 static constexpr auto enum_string =
219 enum_string_with_options<json_custom_opts_def>;
224 template<json_options_t NumberOptions>
225 static constexpr auto enum_string_or_number_with_options =
226 refl_details::refl_enum_string_or_number{ NumberOptions };
228 static constexpr auto enum_string_or_number =
229 enum_string_or_number_with_options<number_opts_def>;
231 struct reflect_all_t : reflect_base_t, refl_details::reflect_all_t {};
232 struct reflect_t : reflect_base_t {
233 static constexpr auto unchecked = reflect_all_t{ };
236 inline constexpr auto reflect = reflect_t{ };
241 inline constexpr bool enable_reflection_for =
false;
244 concept ReflectionEnabled =
245 std::is_class_v<T> and
246 ( enable_reflection_for<T> or
247 refl_details::has_annotation<reflect_base_t, T>( ) or
248 refl_details::has_reflected_submembers<T>( ) );
250 template<ReflectionEnabled T>
251 struct json_data_contract<T> {
252 using constructor_t = refl_details::reflected_constructor<T>;
254 using type =
typename[:refl_details::get_json_member_list<T>( ):];
256 DAW_ATTRIB_INLINE
static constexpr auto to_json_data( T
const &value ) {
257 return refl_details::to_tuple( value );
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
DAW_ATTRIB_NOINLINE void daw_json_error(bool b, ErrorReason reason)
json_base::json_custom< T, FromJsonConverter, ToJsonConverter, Options > json_custom_no_name
basic_json_value<> json_value
An untyped JSON value.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.