27 inline namespace experimental {
28 template<
typename E, json_options_t Options = json_custom_opts_def>
50 namespace refl_details {
51 template<
auto... vals>
52 struct replicator_type {
54 constexpr void operator>>( F body )
const {
55 ( body.template operator( )<vals>( ), ... );
59 template<
auto... vals>
60 replicator_type<vals...> replicator = { };
63 consteval std::vector<std::meta::info>
64 pub_nsdm_of( std::meta::info type_class ) {
65 auto members = std::meta::nonstatic_data_members_of(
66 type_class, std::meta::access_context::unprivileged( ) );
67 std::erase_if( members, []( std::meta::info
const &i ) {
68 return not std::meta::is_public( i );
74 consteval auto expand( R range ) {
75 auto args = std::vector<std::meta::info>( );
76 for(
auto r : range ) {
77 args.push_back( std::meta::reflect_constant( r ) );
79 return std::meta::substitute(
DAW_REFLECT( replicator ), args );
83 consteval std::optional<T> get_annotaion( std::meta::info r ) {
84 for( std::meta::info a :
std::meta::annotations_of( r ) ) {
86 return std::meta::extract<T>( a );
93 consteval bool has_annotation( std::meta::info r, T
const &value ) {
94 auto expected = std::meta::reflect_constant( value );
95 for( std::meta::info a :
std::meta::annotations_of( r ) ) {
96 if( constant_of( a ) == expected ) {
103 template<
typename T, std::size_t... Is>
104 consteval auto to_tuple( T
const &value, std::index_sequence<Is...> )
105 ->
decltype( std::tuple{
106 value.DAW_SPLICE( pub_nsdm_of(
DAW_REFLECT( T ) )[Is] )... } ) {
108 value.DAW_SPLICE( pub_nsdm_of(
DAW_REFLECT( T ) )[Is] )... };
112 consteval auto to_tuple( T
const &value )
113 ->
decltype( refl_details::to_tuple(
114 value, std::make_index_sequence<
116 return refl_details::to_tuple(
117 value, std::make_index_sequence<
121 template<JSONNAMETYPE Name,
typename T>
122 using deduce_t =
typename json_details::ensure_mapped_t<
123 json_details::json_deduced_type<T>>::template with_name<Name>;
125 template<
typename T, std::
size_t Idx>
126 using submember_type_t =
127 std::tuple_element_t<Idx, DAW_TYPEOF( refl_details::to_tuple(
128 std::declval<T>( ) ) )>;
130 template<
typename T, std::
size_t Idx>
131 consteval auto get_member_link_func( ) {
132 static constexpr auto member_info =
134 static constexpr auto annot_rename =
135 get_annotaion<daw::json::refl_rename>( member_info );
137 static constexpr std::string_view name =
138 annot_rename ? std::string_view( annot_rename->name )
139 :
std::meta::identifier_of( member_info );
140 static_assert( not name.empty( ),
"Unexpected empty name" );
142 static constexpr auto annot_map_as = [] {
143 static constexpr auto refl_map_as_annot =
144 get_annotaion<refl_map_as>( member_info );
145 static constexpr auto refl_enum_string_annot =
146 get_annotaion<refl_enum_string>( member_info );
147 if constexpr( refl_map_as_annot ) {
148 static_assert( not refl_enum_string_annot,
149 "Do not use reflect.enum_string and reflect.map_as "
150 "at the same time" );
151 return refl_map_as_annot;
152 }
else if constexpr( refl_enum_string_annot ) {
153 using json_member_no_name =
155 std::meta::type_of( member_info ) ),
156 refl_enum_string_annot->Options>;
157 static constexpr auto info =
158 DAW_REFLECT(
typename json_member_no_name::template with_name<
159 json_name<name.size( ) + 1>(
161 std::make_index_sequence<name.size( ) + 1>{ } )> );
162 return std::optional<refl_map_as>{ refl_map_as{ info } };
168 if constexpr( annot_map_as ) {
171 "Do not use reflect.rename and reflect.map_as at the same time" );
172 static constexpr auto result =
173 daw::traits::identity<
typename DAW_SPLICE( annot_map_as->type )>{ };
176 return daw::traits::identity<deduce_t<
177 json_name<name.size( ) + 1>(
178 name.data( ), std::make_index_sequence<name.size( ) + 1>{ } ),
179 submember_type_t<T, Idx>>>{ };
183 template<
typename T, std::
size_t Idx>
184 using get_member_link_t =
185 typename DAW_TYPEOF( get_member_link_func<T, Idx>( ) )::type;
187 template<
typename,
typename>
188 struct make_data_contract;
190 template<
typename,
typename...>
191 inline constexpr bool construction_test_v =
false;
193 template<
typename T,
typename... Ts>
194 inline constexpr bool construction_test_v<T, std::tuple<Ts...>> =
196 T{ std::declval<Ts>( )... };
200 concept Reflectable =
201 not std::is_empty_v<T> and std::is_class_v<T> and
requires {
202 refl_details::to_tuple( std::declval<T>( ) );
204 and construction_test_v<T, DAW_TYPEOF( refl_details::to_tuple(
205 std::declval<T>( ) ) )>;
207 template<Reflectable T, std::size_t... Is>
208 struct make_data_contract<T,
std::index_sequence<Is...>> {
209 using type = json_member_list<get_member_link_t<T, Is>...>;
211 DAW_ATTRIB_INLINE
static constexpr auto to_json_data( T
const &value ) {
212 return daw::forward_nonrvalue_as_tuple(
213 value.DAW_SPLICE( pub_nsdm_of(
DAW_REFLECT( T ) )[Is] )... );
218 requires std::is_enum_v<E>
constexpr E
219 enum_from_string( std::string_view name ) {
220 template for(
constexpr auto enumerator :
222 if( name == std::meta::identifier_of( enumerator ) ) {
242 requires std::is_enum_v<E>
constexpr std::string_view
243 enum_to_string( E value ) {
244 auto result = std::string_view{ };
248 result = std::meta::identifier_of( e );
255 requires std::is_enum_v<E>
struct reflect_enum_as_string {
256 static constexpr E operator( )( std::string_view name ) {
257 return enum_from_string<E>( name );
260 static constexpr std::string_view operator( )( E value ) {
261 return enum_to_string( value );
266 template<
typename E, json_options_t Options>
269 refl_details::reflect_enum_as_string<E>, Options> {
277 template<
typename JsonMember>
283 daw::json::refl_ignore_with_default{ };
290 template<json_options_t Options>
292 daw::json::refl_enum_string{ Options };
295 enum_string_with_opt<json_custom_opts_def>;
299 template<refl_details::Reflectable T>