Skip to content

Commit d3a97d4

Browse files
committed
Fixes
1 parent ebb0d3e commit d3a97d4

File tree

3 files changed

+176
-199
lines changed

3 files changed

+176
-199
lines changed

universal/include/userver/formats/universal/common_containers.hpp

Lines changed: 95 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -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
};
7777
template <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

8388
template <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
};
8896
template <>
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+
94106
template <utils::ConstexprString Pattern>
95107
static 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+
110123
struct 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+
196198
template <>
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-
218219
template <>
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+
279241
template <typename Value>
280242
struct 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
};
358320
template <typename Element>
359321
struct 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

Comments
 (0)