@@ -19,8 +19,8 @@ struct Max : public impl::Param<T> {
1919 return this ->Error (value);
2020 }
2121 template <typename Value>
22- inline constexpr std:: enable_if_t <meta:: kIsRange < Value>, std::optional<std::string> >
23- Check ( const Value& value) const {
22+ inline constexpr auto Check ( const Value& value) const -> std::optional<std::string>
23+ requires meta::kIsRange<Value> {
2424 for (const auto & element : value) {
2525 if (element > this ->value ) {
2626 return this ->Error (element);
@@ -38,7 +38,7 @@ struct MinElements : public impl::Param<std::size_t> {
3838 inline constexpr MinElements (const std::size_t & value) :
3939 impl::Param<std::size_t>(value) {}
4040 template <typename Value>
41- inline constexpr std::optional<std::string> Check (const Value& value) const {
41+ inline constexpr auto Check (const Value& value) const -> std::optional<std::string> {
4242 if (value.size () >= this ->value ) {
4343 return std::nullopt ;
4444 }
@@ -59,10 +59,10 @@ struct Min : public impl::Param<T> {
5959 return std::nullopt ;
6060 }
6161 return this ->Error (value);
62- };
62+ }
6363 template <typename Value>
64- inline constexpr std:: enable_if_t <meta:: kIsRange < Value>, std::optional<std::string> >
65- Check ( const Value& value) const {
64+ inline constexpr auto Check ( const Value& value) const -> std::optional<std::string>
65+ requires meta::kIsRange<Value> {
6666 for (const auto & element : value) {
6767 if (element < this ->value ) {
6868 return this ->Error (element);
@@ -72,25 +72,37 @@ struct Min : public impl::Param<T> {
7272 }
7373 inline constexpr auto Error (const T& value) const {
7474 return std::format (" {} < {}" , value, this ->value );
75- };
75+ }
7676};
7777template <typename T, typename = void >
78- struct Default : public impl ::EmptyCheck, public impl::Param<T(*)()> {
78+ struct Default : public impl ::EmptyCheck, private impl::Param<T(*)()> {
7979 inline constexpr Default (T (*ptr)()) :
8080 impl::Param<T(*)()>(ptr) {}
81+ inline constexpr Default (auto f) requires requires {static_cast <T (*)()>(f);} :
82+ impl::Param<T(*)()>(static_cast <T(*)()>(f)) {}
83+ inline constexpr auto value () const {
84+ return static_cast <const impl::Param<T (*)()>&>(*this ).value ();
85+ }
8186};
8287
8388template <typename T>
84- struct Default <T, std::enable_if_t <std::is_arithmetic_v<T>, void >> : public impl::EmptyCheck, public impl::Param<T> {
89+ struct Default <T, std::enable_if_t <std::is_arithmetic_v<T>>> : public impl::EmptyCheck, private impl::Param<T> {
8590 inline constexpr Default (const T& value) :
8691 impl::Param<T>(value) {}
92+ inline constexpr auto value () const {
93+ return static_cast <const impl::Param<T>&>(*this ).value ;
94+ }
8795};
8896template <>
89- struct Default <std::string, void > : public impl::EmptyCheck, public impl::Param<std::string_view> {
97+ struct Default <std::string, void > : public impl::EmptyCheck, private impl::Param<std::string_view> {
9098 inline constexpr Default (std::string_view value) :
9199 impl::Param<std::string_view>(value) {}
100+ inline constexpr auto value () const -> std::string {
101+ return static_cast <std::string>(static_cast <const impl::Param<std::string_view>&>(*this ).value );
102+ }
92103};
93104
105+
94106template <utils::ConstexprString Pattern>
95107static const utils::regex kRegex (Pattern);
96108
@@ -107,175 +119,125 @@ struct Pattern : public impl::EmptyCheck, public impl::Param<const utils::regex*
107119 return " Error" ;
108120 }
109121};
122+
110123struct Additional : public impl ::EmptyCheck, public impl::Param<bool > {
111124 constexpr inline Additional (const bool & value) :
112125 impl::Param<bool>(value) {}
113126};
114- template <>
115- struct FieldConfig <int > {
116- std::optional<Max<int >> Maximum = std::nullopt ;
117- std::optional<Min<int >> Minimum = std::nullopt ;
118- template <typename MainClass, auto I, typename Value>
119- constexpr int Read (Value&& value) const {
120- constexpr auto name = boost::pfr::get_name<I, MainClass>();
121- return value[name].template As <int >();
122- };
123- template <typename MainClass, auto I, typename Value>
124- constexpr std::optional<int > TryRead (Value&& value) const {
125- constexpr auto name = boost::pfr::get_name<I, MainClass>();
126- return parse::TryParse (value[name], parse::To<int >{});
127- };
128- constexpr auto Write (const int & value, std::string_view fieldName, const auto &, auto & builder) const {
129- builder[static_cast <std::string>(fieldName)] = value;
130- };
131- inline constexpr std::optional<std::string> Check (const int &) const {
132- return std::nullopt ;
133- }
134127
135- };
136- template <>
137- struct FieldConfig <std::optional<std::string>> {
138- std::optional<Pattern> Pattern = std::nullopt ;
139- std::optional<Default<std::string>> Default = std::nullopt ;
128+ template <typename T>
129+ struct FieldConfig <std::optional<T>> {
130+ FieldConfig<T> Main = {};
131+ std::optional<Default<T>> Default = std::nullopt ;
140132 bool Required = false ;
141133 bool Nullable = false ;
134+ static inline constexpr auto Checker (const auto & check, const auto & value) -> std::optional<std::string>
135+ requires requires{check.Check (*value);} {
136+ if (value) {
137+ return check.Check (*value);
138+ };
139+ return std::nullopt ;
140+ };
141+ constexpr inline std::optional<std::string> Check (const std::optional<T>&) const {
142+ return std::nullopt ;
143+ }
144+ constexpr auto Write (const std::optional<T>& value, std::string_view fieldName, const auto &, auto & builder) const {
145+ if (value) {
146+ builder[static_cast <std::string>(fieldName)] = *value;
147+ return ;
148+ }
149+ if (this ->Default ) {
150+ builder[static_cast <std::string>(fieldName)] = this ->Default ->value ();
151+ return ;
152+ }
153+ }
142154 template <typename MainClass, auto I, typename Value>
143- constexpr std::optional<std::string > Read (Value&& value) const {
155+ constexpr std::optional<T > Read (Value&& value) const {
144156 constexpr auto name = boost::pfr::get_name<I, MainClass>();
145- if (value[name].IsMissing () && this -> Required ) {
157+ if (this -> Required && value[name].IsMissing ()) {
146158 return std::nullopt ;
147- };
159+ }
148160 if (!value[name].IsMissing ()) {
149161 if (this ->Nullable ) {
150- return value[name].template As <std::optional<std::string >>();
151- };
152- return value[name].template As <std::string >();
153- };
162+ return value[name].template As <std::optional<T >>();
163+ }
164+ return value[name].template As <T >();
165+ }
154166 if (this ->Default ) {
155- return static_cast <std::string>( this ->Default ->value );
156- };
167+ return this ->Default ->value ( );
168+ }
157169 return std::nullopt ;
158- };
170+ }
159171 template <typename MainClass, auto I, typename Value>
160- constexpr std::optional<std::optional<std::string >> TryRead (Value&& value) const {
172+ constexpr std::optional<std::optional<T >> TryRead (Value&& value) const {
161173 constexpr auto name = boost::pfr::get_name<I, MainClass>();
162174 if (value[name].IsMissing () && this ->Required ) {
163175 return std::nullopt ;
164- };
165-
176+ }
166177 if (this ->Nullable ) {
167- auto response = parse::TryParse (value[name], parse::To<std::optional<std::string >>{});
178+ std::optional response = parse::TryParse (value[name], parse::To<std::optional<T >>{});
168179 if (response) {
169180 return response;
170181 }
171182 } else {
172- auto response = parse::TryParse (value[name], parse::To<std::string>{});
183+ if (value[name].IsNull ()) {
184+ return std::nullopt ;
185+ };
186+ auto response = parse::TryParse (value[name], parse::To<T>{});
173187 if (response) {
174188 return response;
175- };
176- };
189+ }
190+ }
177191 if (this ->Default ) {
178- return static_cast <std::string>( this ->Default ->value );
192+ return this ->Default ->value ( );
179193 }
180194 return {{}};
181195 }
182- constexpr auto Write (const std::optional<std::string>& value, std::string_view fieldName, const auto &, auto & builder) const {
183- if (value) {
184- builder[static_cast <std::string>(fieldName)] = *value;
185- return ;
186- };
187- if (this ->Default ) {
188- builder[static_cast <std::string>(fieldName)] = this ->Default ->value ;
189- };
190- };
191- inline constexpr std::optional<std::string> Check (const auto &) const {
192- return std::nullopt ;
193- }
194-
195196};
197+
196198template <>
197- struct FieldConfig <std::string> {
198- std::optional<Pattern> Pattern = std::nullopt ;
199+ struct FieldConfig <int > {
200+ std::optional<Max<int >> Maximum = std::nullopt ;
201+ std::optional<Min<int >> Minimum = std::nullopt ;
199202 template <typename MainClass, auto I, typename Value>
200- constexpr std::string Read (Value&& value) const {
203+ constexpr int Read (Value&& value) const {
201204 constexpr auto name = boost::pfr::get_name<I, MainClass>();
202- return value[name].template As <std::string >();
203- };
205+ return value[name].template As <int >();
206+ }
204207 template <typename MainClass, auto I, typename Value>
205- constexpr std::optional<std::string > TryRead (Value&& value) const {
208+ constexpr std::optional<int > TryRead (Value&& value) const {
206209 constexpr auto name = boost::pfr::get_name<I, MainClass>();
207- return parse::TryParse (value[name], parse::To<std::string >{});
208- };
209- constexpr auto Write (std::string_view value, std::string_view fieldName, const auto &, auto & builder) const {
210+ return parse::TryParse (value[name], parse::To<int >{});
211+ }
212+ constexpr auto Write (const int & value, std::string_view fieldName, const auto &, auto & builder) const {
210213 builder[static_cast <std::string>(fieldName)] = value;
211- };
212- inline constexpr std::optional<std::string> Check (std::string_view ) const {
214+ }
215+ inline constexpr std::optional<std::string> Check (const int & ) const {
213216 return std::nullopt ;
214217 }
215-
216218};
217-
218219template <>
219- struct FieldConfig <std::optional<int >> {
220- std::optional<Max<int >> Maximum = std::nullopt ;
221- std::optional<Min<int >> Minimum = std::nullopt ;
222- std::optional<Default<int >> Default = std::nullopt ;
223- bool Required = false ;
224- bool Nullable = false ;
220+ struct FieldConfig <std::string> {
221+ std::optional<Pattern> Pattern = std::nullopt ;
225222 template <typename MainClass, auto I, typename Value>
226- constexpr std::optional< int > Read (Value&& value) const {
223+ constexpr std::string Read (Value&& value) const {
227224 constexpr auto name = boost::pfr::get_name<I, MainClass>();
228- if (value[name].IsMissing () && this ->Required ) {
229- return std::nullopt ;
230- };
231- if (!value[name].IsMissing ()) {
232- if (this ->Nullable ) {
233- return value[name].template As <std::optional<int >>();
234- };
235- return value[name].template As <int >();
236- }
237- if (this ->Default ) {
238- return this ->Default ->value ;
239- }
240- return std::nullopt ;
225+ return value[name].template As <std::string>();
241226 }
242227 template <typename MainClass, auto I, typename Value>
243- constexpr std::optional<std::optional< int > > TryRead (Value&& value) const {
228+ constexpr std::optional<std::string > TryRead (Value&& value) const {
244229 constexpr auto name = boost::pfr::get_name<I, MainClass>();
245- if (this ->Nullable ) {
246- auto response = parse::TryParse (value[name], parse::To<std::optional<int >>{});
247- if (response) {
248- return response;
249- }
250- } else {
251- if (value[name].IsNull ()) {
252- return std::nullopt ;
253- };
254- auto response = parse::TryParse (value[name], parse::To<int >{});
255- if (response) {
256- return response;
257- };
258- };
259- if (this ->Default ) {
260- return this ->Default ->value ;
261- }
262- return {{}};
230+ return parse::TryParse (value[name], parse::To<std::string>{});
263231 }
264- constexpr auto Write (const std::optional<int >& value, std::string_view fieldName, const auto &, auto & builder) const {
265- if (value) {
266- builder[static_cast <std::string>(fieldName)] = *value;
267- return ;
268- }
269- if (this ->Default ) {
270- builder[static_cast <std::string>(fieldName)] = this ->Default ->value ;
271- }
232+ constexpr auto Write (std::string_view value, std::string_view fieldName, const auto &, auto & builder) const {
233+ builder[static_cast <std::string>(fieldName)] = value;
272234 }
273-
274- inline constexpr std::optional<std::string> Check (const std::optional<int >&) const {
235+ inline constexpr std::optional<std::string> Check (std::string_view) const {
275236 return std::nullopt ;
276237 }
277238
278239};
240+
279241template <typename Value>
280242struct FieldConfig <std::unordered_map<std::string, Value>> {
281243 std::optional<Additional> Additional = std::nullopt ;
@@ -345,15 +307,15 @@ struct FieldConfig<std::unordered_map<std::string, Value>> {
345307 if (this ->Additional ) {
346308 for (const auto & [name, value2] : value) {
347309 builder[name] = value2;
348- };
310+ }
349311 return ;
350- };
312+ }
351313 Builder newBuilder;
352314 for (const auto & [name, value2] : value) {
353315 newBuilder[name] = value2;
354- };
316+ }
355317 builder[static_cast <std::string>(fieldName)] = newBuilder.ExtractValue ();
356- };
318+ }
357319};
358320template <typename Element>
359321struct FieldConfig <std::vector<Element>> {
@@ -390,7 +352,7 @@ struct FieldConfig<std::vector<Element>> {
390352 if (!error) {
391353 error = add;
392354 continue ;
393- };
355+ }
394356 *error += *add;
395357 }
396358 }
0 commit comments