DAW JSON Link
Loading...
Searching...
No Matches
daw_json_reflection.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
12
14
15#if defined( DAW_JSON_HAS_REFLECTION )
18
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>
23
24#include <cstddef>
25#include <meta>
26#include <string_view>
27#include <tuple>
28#include <type_traits>
29#include <utility>
30#include <vector>
31
32namespace daw::json::inline DAW_JSON_VER::refl_details {
33 template<typename D>
34 struct refl_ignored_value : refl_annotation_base, refl_ignored_base {
35 D default_value;
36
37 explicit constexpr refl_ignored_value( D value )
38 : default_value( value ) {}
39
40 template<typename T>
41 constexpr operator T( ) const {
42 if constexpr( std::is_convertible_v<D, T> ) {
43 return default_value;
44 } else if constexpr( requires( D v ) {
45 { v( ) }->std::convertible_to<T>;
46 } ) {
47 return default_value( );
48 }
49 }
50 };
51
52 struct refl_ignored : refl_annotation_base, refl_ignored_base {
53 explicit consteval refl_ignored( ) = default;
54
55 template<typename T>
56 static consteval auto operator( )( T &&rhs ) {
57 return refl_ignored_value<T>{ DAW_FWD( rhs ) };
58 }
59
60 template<typename T>
61 consteval operator T( ) const {
62 return T{ };
63 }
64 };
65
66 struct member_reflection_t {};
67
68 template<typename T, std::size_t Idx>
69 using submember_type_t = std::tuple_element_t<Idx, to_tuple_t<T>>;
70
71 template<EnumType E>
72 constexpr E enum_from_string( std::string_view name ) {
73 template for( constexpr auto enumerator : enumerators_of( ^^E ) ) {
74 // TODO add name formatting e.g lower/upper/first capital
75 if( name == identifier_of( enumerator ) ) {
76 return [:enumerator:];
77 }
78 }
79 daw_json_ensure( daw::pipelines::Contains( name )( enumerators_of( ^^E ) ),
80 ErrorReason::InvalidString );
81 }
82
83 template<EnumType E>
84 constexpr std::string_view enum_to_string( E value ) {
85 static constexpr auto enums =
86 reflect_constant_array( enumerators_of( ^^E ) );
87 template for( constexpr auto enumerator : [:enums:] ) {
88 if( value == [:enumerator:] ) {
89 return identifier_of( enumerator );
90 }
91 }
92 return std::string_view{ };
93 }
94
95 template<EnumType E>
96 struct reflect_enum_as_string {
97 static constexpr E operator( )( std::string_view name ) {
98 return enum_from_string<E>( name );
99 }
100
101 static constexpr std::string_view operator( )( E value ) {
102 return enum_to_string( value );
103 }
104 };
105 template<typename T, std::size_t... Idx>
106 consteval std::meta::info
107 get_json_members_list_impl( std::index_sequence<Idx...> ) {
108 return ^^json_member_list<get_member_link_t<T, Idx>...>;
109 }
110
111 template<typename T>
112 consteval std::meta::info get_json_member_list( ) {
113 static constexpr auto sz =
114 get_non_ignored_reflectible_members<T>( ).size( );
115 return get_json_members_list_impl<T>( std::make_index_sequence<sz>{ } );
116 }
117
118 template<EnumType E, json_options_t Options>
119 struct enum_string : json_custom_no_name<E, reflect_enum_as_string<E>,
120 reflect_enum_as_string<E>, Options> {
121 };
122
123 template<Reflectable T>
124 consteval bool has_reflected_submembers( ) {
125 static constexpr auto members = [:as_stdarray(
126 get_reflectible_members<T>( ) ):];
127 template for( constexpr auto member : members ) {
128 if( not annotations_of_with_base_type( member, ^^refl_annotation_base )
129 .empty( ) ) {
130 return true;
131 }
132 }
133 return false;
134 }
135
136} // namespace daw::json::inline DAW_JSON_VER::refl_details
137namespace daw::json::inline DAW_JSON_VER {
138
142 struct reflect_base_t {
143
146 template<json_name Name>
147 static constexpr auto rename = refl_details::refl_rename{ Name.m_data };
148
149 template<typename JsonMember>
150 static constexpr auto map_as = refl_details::refl_map_as{ ^^JsonMember };
151
155 static constexpr auto ignored = refl_details::refl_ignored{ };
156
158 template<json_options_t Options>
159 static constexpr auto enum_string_with_options =
160 refl_details::refl_enum_string{ Options };
161
162 static constexpr auto enum_string =
163 enum_string_with_options<json_custom_opts_def>;
164 };
165 struct reflect_all_t : reflect_base_t, refl_details::reflect_all_t {};
166 struct reflect_t : reflect_base_t {
167 static constexpr auto unchecked = reflect_all_t{ };
168 };
169
170 inline constexpr auto reflect = reflect_t{ };
171} // namespace daw::json::inline DAW_JSON_VER
172
173namespace daw::json::inline DAW_JSON_VER {
174 template<typename T>
175 inline constexpr bool enable_reflection_for = false;
176
177 template<typename T>
178 concept ReflectionEnabled =
179 enable_reflection_for<T> or
180 refl_details::has_annotation<reflect_base_t, T>( ) or
181 refl_details::has_reflected_submembers<T>( );
182
183 template<ReflectionEnabled T>
184 struct json_data_contract<T> {
185 using constructor_t = refl_details::reflected_constructor<T>;
186
187 using type = typename[:refl_details::get_json_member_list<T>( ):];
188
189 DAW_ATTRIB_INLINE static constexpr auto to_json_data( T const &value ) {
190 return refl_details::to_tuple( value );
191 }
192 };
193} // namespace daw::json::inline DAW_JSON_VER
194
195#endif
#define daw_json_ensure(Bool,...)
Ensure that Bool is true. If false pass rest of args to daw_json_error.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20