11 #include "daw/daw_pipelines.h"
15 #include <experimental/meta>
17 #include <type_traits>
21 #define DAW_REFL( ... ) ^^__VA_ARGS__
22 #define DAW_SPLICE( ... ) [:__VA_ARGS__:]
25 inline namespace experimental {
26 template<
typename E, json_options_t Options = json_custom_opts_def>
48 namespace refl_details {
49 template<
auto... vals>
50 struct replicator_type {
52 constexpr
void operator>>( F body )
const {
53 ( body.template operator( )<vals>( ), ... );
57 template<
auto... vals>
58 replicator_type<vals...> replicator = { };
61 consteval std::vector<std::meta::info>
62 pub_nsdm_of( std::meta::info type_class ) {
63 auto members = std::meta::nonstatic_data_members_of( type_class );
64 std::erase_if( members, []( std::meta::info
const &i ) {
65 return not std::meta::is_public( i );
71 consteval
auto expand( R range ) {
72 auto args = std::vector<std::meta::info>( );
73 for(
auto r : range ) {
74 args.push_back( std::meta::reflect_value( r ) );
76 return std::meta::substitute(
DAW_REFL( replicator ), args );
80 consteval std::optional<T> get_annotaion( std::meta::info r ) {
81 for( std::meta::info a : std::meta::annotations_of( r ) ) {
82 if( std::meta::type_of( a ) ==
DAW_REFL( T ) ) {
83 return std::meta::extract<T>( a );
90 consteval
bool has_annotation( std::meta::info r, T
const &value ) {
91 auto expected = std::meta::reflect_value( value );
92 for( std::meta::info a : std::meta::annotations_of( r ) ) {
93 if( value_of( a ) == expected ) {
100 template<
typename T, std::size_t... Is>
101 consteval
auto to_tuple( T
const &value, std::index_sequence<Is...> )
102 -> decltype( std::tuple(
103 value.DAW_SPLICE( pub_nsdm_of(
DAW_REFL( T ) )[Is] )... ) ) {
105 value.DAW_SPLICE( pub_nsdm_of(
DAW_REFL( T ) )[Is] )... );
110 to_tuple( T
const &value ) -> decltype( refl_details::to_tuple(
112 std::make_index_sequence<pub_nsdm_of(
DAW_REFL( T ) ).size( )>{ } ) ) {
113 return refl_details::to_tuple(
115 std::make_index_sequence<pub_nsdm_of(
DAW_REFL( T ) ).size( )>{ } );
118 template<JSONNAMETYPE Name,
typename T>
119 using deduce_t =
typename json_details::ensure_mapped_t<
120 json_details::json_deduced_type<T>>::template with_name<Name>;
122 template<
typename T, std::
size_t Idx>
123 using submember_type_t =
124 std::tuple_element_t<Idx, DAW_TYPEOF( refl_details::to_tuple(
125 std::declval<T>( ) ) )>;
127 template<
typename T, std::
size_t Idx>
128 consteval
auto get_member_link_func( ) {
129 static constexpr
auto member_info = pub_nsdm_of(
DAW_REFL( T ) )[Idx];
130 static constexpr
auto annot_rename =
131 get_annotaion<daw::json::refl_rename>( member_info );
133 static constexpr std::string_view name =
134 annot_rename ? std::string_view( annot_rename->name )
135 :
std::meta::identifier_of( member_info );
136 static_assert( not name.empty( ),
"Unexpected empty name" );
138 static constexpr
auto annot_map_as = [] {
139 static constexpr
auto refl_map_as_annot =
140 get_annotaion<refl_map_as>( member_info );
141 static constexpr
auto refl_enum_string_annot =
142 get_annotaion<refl_enum_string>( member_info );
143 if constexpr( refl_map_as_annot ) {
144 static_assert( not refl_enum_string_annot,
145 "Do not use reflect.enum_string and reflect.map_as "
146 "at the same time" );
147 return refl_map_as_annot;
148 }
else if constexpr( refl_enum_string_annot ) {
149 using json_member_no_name =
151 std::meta::type_of( member_info ) ),
152 refl_enum_string_annot->Options>;
153 static constexpr
auto info =
154 DAW_REFL(
typename json_member_no_name::template with_name<
155 json_name<name.size( ) + 1>(
157 std::make_index_sequence<name.size( ) + 1>{ } )> );
158 return std::optional<refl_map_as>{ refl_map_as{ info } };
164 if constexpr( annot_map_as ) {
167 "Do not use reflect.rename and reflect.map_as at the same time" );
168 static constexpr
auto result =
169 daw::traits::identity<
DAW_SPLICE( annot_map_as->type )>{ };
172 return daw::traits::identity<deduce_t<
173 json_name<name.size( ) + 1>(
174 name.data( ), std::make_index_sequence<name.size( ) + 1>{ } ),
175 submember_type_t<T, Idx>>>{ };
179 template<
typename T, std::
size_t Idx>
180 using get_member_link_t =
181 typename DAW_TYPEOF( get_member_link_func<T, Idx>( ) )::type;
183 template<
typename,
typename>
184 struct make_data_contract;
186 template<
typename,
typename...>
187 inline constexpr
bool construction_test_v =
false;
189 template<
typename T,
typename... Ts>
190 inline constexpr
bool construction_test_v<T, std::tuple<Ts...>> =
192 T{ std::declval<Ts>( )... };
196 concept Reflectable =
197 not std::is_empty_v<T> and std::is_class_v<T> and
requires {
198 refl_details::to_tuple( std::declval<T>( ) );
200 and construction_test_v<T, DAW_TYPEOF( refl_details::to_tuple(
201 std::declval<T>( ) ) )>;
203 template<Reflectable T, std::size_t... Is>
204 struct make_data_contract<T,
std::index_sequence<Is...>> {
205 using type = json_member_list<get_member_link_t<T, Is>...>;
207 DAW_ATTRIB_INLINE
static constexpr
auto to_json_data( T
const &value ) {
208 return daw::forward_nonrvalue_as_tuple(
209 value.DAW_SPLICE( pub_nsdm_of(
DAW_REFL( T ) )[Is] )... );
214 requires std::is_enum_v<E> constexpr E
215 enum_from_string( std::string_view name ) {
216 template for( constexpr
auto enumerator :
217 std::meta::enumerators_of(
DAW_REFL( E ) ) ) {
218 if( name == std::meta::identifier_of( enumerator ) ) {
238 requires std::is_enum_v<E> constexpr std::string_view
239 enum_to_string( E value ) {
240 auto result = std::string_view{ };
244 result = std::meta::identifier_of( e );
251 requires std::is_enum_v<E>
struct reflect_enum_as_string {
252 static constexpr E operator( )( std::string_view name ) {
253 return enum_from_string<E>( name );
256 static constexpr std::string_view operator( )( E value ) {
257 return enum_to_string( value );
262 template<
typename E, json_options_t Options>
265 refl_details::reflect_enum_as_string<E>, Options> {
273 template<
typename JsonMember>
277 daw::json::refl_ignore_with_default{ };
284 template<json_options_t Options>
286 daw::json::refl_enum_string{ Options };
289 enum_string_with_opt<json_custom_opts_def>;
293 template<refl_details::Reflectable T>
301 : refl_details::make_data_contract<
302 T, std::make_index_sequence<
303 refl_details::pub_nsdm_of( DAW_REFL( T ) ).size( )>> {};
DAW_ATTRIB_NOINLINE void daw_json_error(ErrorReason reason)
json_base::json_custom< T, FromJsonConverter, ToJsonConverter, Options > json_custom_no_name
std::uint32_t json_options_t
constexpr bool is_reflectible_type_v
constexpr struct daw::json::inline::experimental::reflect_t reflect
requires(std::is_aggregate_v< T > and std::is_class_v< T > and not std::is_empty_v< T >) inline const expr bool use_boost_pfr
Enable Boost PFR mappings for a type.
Mapping class for JSON data structures to C++. It must be specialized in order to parse to a user cla...
static consteval refl_rename rename(char const *name)
static constexpr auto ignore_with_default
static consteval auto ignore_with_value(T &&v)
static constexpr auto enum_string_with_opt
static constexpr auto map_as
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.