Skip to content

Commit 8e942ae

Browse files
committed
Fixes
1 parent 8986d53 commit 8e942ae

File tree

4 files changed

+73
-44
lines changed

4 files changed

+73
-44
lines changed

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

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <userver/formats/common/items.hpp>
55
#include <userver/formats/parse/try_parse.hpp>
66
#include <format>
7+
#include <unordered_map>
78
#include <userver/utils/regex.hpp>
89

910
USERVER_NAMESPACE_BEGIN
@@ -123,8 +124,8 @@ struct Pattern : public impl::EmptyCheck, public impl::Param<const utils::regex*
123124
}
124125
};
125126

126-
struct Additional : public impl::EmptyCheck, public impl::Param<bool> {
127-
constexpr inline Additional(const bool& value) :
127+
struct AdditionalProperties : public impl::EmptyCheck, public impl::Param<bool> {
128+
constexpr inline AdditionalProperties(const bool& value) :
128129
impl::Param<bool>(value) {}
129130
};
130131

@@ -147,13 +148,13 @@ struct FieldConfig<std::optional<T>> {
147148
};
148149
return std::nullopt;
149150
}
150-
constexpr auto Write(const std::optional<T>& value, std::string_view fieldName, const auto& names, auto& builder) const {
151+
constexpr auto Write(const std::optional<T>& value, std::string_view field_name, const auto& names, auto& builder) const {
151152
if(value) {
152-
this->Main.Write(*value, fieldName, names, builder);
153+
this->Main.Write(*value, field_name, names, builder);
153154
return;
154155
}
155156
if(this->Default) {
156-
this->Main.Write(this->Default->value(), fieldName, names, builder);
157+
this->Main.Write(this->Default->value(), field_name, names, builder);
157158
return;
158159
}
159160
}
@@ -202,22 +203,22 @@ struct FieldConfig<std::optional<T>> {
202203
}
203204
};
204205

205-
template <>
206-
struct FieldConfig<int> {
207-
std::optional<Max<int>> Maximum = std::nullopt;
208-
std::optional<Min<int>> Minimum = std::nullopt;
206+
template <typename T>
207+
struct FieldConfig<T, std::enable_if_t<meta::kIsInteger<T> || std::is_floating_point_v<T>>> {
208+
std::optional<Max<T>> Maximum = std::nullopt;
209+
std::optional<Min<T>> Minimum = std::nullopt;
209210
template <typename MainClass, auto I, typename Value>
210211
constexpr int Read(Value&& value) const {
211212
constexpr auto name = boost::pfr::get_name<I, MainClass>();
212-
return value[name].template As<int>();
213+
return value[name].template As<T>();
213214
}
214215
template <typename MainClass, auto I, typename Value>
215-
constexpr std::optional<int> TryRead(Value&& value) const {
216+
constexpr std::optional<T> TryRead(Value&& value) const {
216217
constexpr auto name = boost::pfr::get_name<I, MainClass>();
217-
return parse::TryParse(value[name], parse::To<int>{});
218+
return parse::TryParse(value[name], parse::To<T>{});
218219
}
219-
constexpr auto Write(const int& value, std::string_view fieldName, const auto&, auto& builder) const {
220-
builder[static_cast<std::string>(fieldName)] = value;
220+
constexpr auto Write(const int& value, std::string_view field_name, const auto&, auto& builder) const {
221+
builder[static_cast<std::string>(field_name)] = value;
221222
}
222223
inline constexpr std::optional<std::string> Check(const int&) const {
223224
return std::nullopt;
@@ -236,8 +237,8 @@ struct FieldConfig<std::string> {
236237
constexpr auto name = boost::pfr::get_name<I, MainClass>();
237238
return parse::TryParse(value[name], parse::To<std::string>{});
238239
}
239-
constexpr auto Write(std::string_view value, std::string_view fieldName, const auto&, auto& builder) const {
240-
builder[static_cast<std::string>(fieldName)] = value;
240+
constexpr auto Write(std::string_view value, std::string_view field_name, const auto&, auto& builder) const {
241+
builder[static_cast<std::string>(field_name)] = value;
241242
}
242243
inline constexpr std::optional<std::string> Check(std::string_view) const {
243244
return std::nullopt;
@@ -247,13 +248,13 @@ struct FieldConfig<std::string> {
247248

248249
template <typename Value>
249250
struct FieldConfig<std::unordered_map<std::string, Value>> {
250-
std::optional<Additional> Additional = std::nullopt;
251+
std::optional<AdditionalProperties> AdditionalProperties = std::nullopt;
251252
FieldConfig<Value> Items = {};
252253
using Type = std::unordered_map<std::string, Value>;
253254
template <typename MainClass, auto I, typename Value2>
254255
inline constexpr Type Read(Value2&& value) const {
255256
Type response;
256-
if(this->Additional) {
257+
if(this->AdditionalProperties) {
257258
constexpr auto fields = boost::pfr::names_as_array<MainClass>();
258259
for(const auto& [name, value] : userver::formats::common::Items(std::forward<Value2>(value))) {
259260
auto it = std::find(fields.begin(), fields.end(), name);
@@ -272,7 +273,7 @@ struct FieldConfig<std::unordered_map<std::string, Value>> {
272273
template <typename MainClass, auto I, typename Value2>
273274
inline constexpr std::optional<Type> TryRead(Value2&& value) const {
274275
Type response;
275-
if(this->Additional) {
276+
if(this->AdditionalProperties) {
276277
constexpr auto fields = boost::pfr::names_as_array<MainClass>();
277278
for(const auto& [name, value] : userver::formats::common::Items(std::forward<Value2>(value))) {
278279
if(std::find(fields.begin(), fields.end(), name) == fields.end()) {
@@ -285,8 +286,8 @@ struct FieldConfig<std::unordered_map<std::string, Value>> {
285286
}
286287
return response;
287288
}
288-
constexpr auto fieldName = boost::pfr::get_name<I, MainClass>();
289-
for(const auto& [name, value] : userver::formats::common::Items(value[fieldName])) {
289+
constexpr auto field_name = boost::pfr::get_name<I, MainClass>();
290+
for(const auto& [name, value] : userver::formats::common::Items(value[field_name])) {
290291
auto New = parse::TryParse(value, parse::To<Value>{});
291292
if(!New) {
292293
return std::nullopt;
@@ -310,8 +311,8 @@ struct FieldConfig<std::unordered_map<std::string, Value>> {
310311
return error;
311312
}
312313
template <typename Builder>
313-
constexpr auto Write(const Type& value, std::string_view fieldName, const auto&, Builder& builder) const {
314-
if(this->Additional) {
314+
constexpr auto Write(const Type& value, std::string_view field_name, const auto&, Builder& builder) const {
315+
if(this->AdditionalProperties) {
315316
for(const auto& [name, value2] : value) {
316317
builder[name] = value2;
317318
}
@@ -321,7 +322,7 @@ struct FieldConfig<std::unordered_map<std::string, Value>> {
321322
for(const auto& [name, value2] : value) {
322323
newBuilder[name] = value2;
323324
}
324-
builder[static_cast<std::string>(fieldName)] = newBuilder.ExtractValue();
325+
builder[static_cast<std::string>(field_name)] = newBuilder.ExtractValue();
325326
}
326327
};
327328
template <typename Element>

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

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,24 @@
66
#include <userver/formats/serialize/to.hpp>
77
#include <userver/utils/meta.hpp>
88
#include <userver/utils/overloaded.hpp>
9+
#include <variant>
910
#include <type_traits>
10-
#include <boost/pfr.hpp>
11+
#include <boost/pfr/core.hpp>
12+
#include <boost/pfr/core_name.hpp>
1113

1214

1315
USERVER_NAMESPACE_BEGIN
1416

1517
namespace formats::universal {
1618

1719

18-
template <typename T>
20+
template <typename T, typename Enable = void>
1921
struct FieldConfig {
2022
constexpr inline std::optional<std::string> Check(const T&) const {
2123
return std::nullopt;
2224
}
23-
constexpr auto Write(const T& value, std::string_view fieldName, const auto&, auto& builder) const {
24-
builder[static_cast<std::string>(fieldName)] = value;
25+
constexpr auto Write(const T& value, std::string_view field_name, const auto&, auto& builder) const {
26+
builder[static_cast<std::string>(field_name)] = value;
2527
}
2628
template <typename MainClass, auto I, typename Value>
2729
constexpr T Read(Value&& value) const {
@@ -40,9 +42,9 @@ template <typename T, std::size_t I>
4042
using kFieldTypeOnIndex = std::remove_reference_t<decltype(boost::pfr::get<I>(std::declval<T>()))>;
4143

4244
template <typename T>
43-
consteval std::size_t getFieldIndexByName(std::string_view fieldName) {
45+
consteval std::size_t getFieldIndexByName(std::string_view field_name) {
4446
constexpr auto names = boost::pfr::names_as_array<T>();
45-
return std::find(names.begin(), names.end(), fieldName) - names.begin();
47+
return std::find(names.begin(), names.end(), field_name) - names.begin();
4648
}
4749

4850
struct Disabled {};
@@ -198,30 +200,44 @@ inline constexpr auto kDeserialization = kSerialization<T>;
198200

199201

200202
template <typename T>
201-
struct SerializationConfig {
202-
using kFieldsConfigType = decltype([]<auto... I>(std::index_sequence<I...>){
203+
class SerializationConfig {
204+
using FieldsConfigType = decltype([]<auto... I>(std::index_sequence<I...>){
203205
return std::type_identity<std::tuple<FieldConfig<impl::kFieldTypeOnIndex<T, I>>...>>();
204206
}(std::make_index_sequence<boost::pfr::tuple_size_v<T>>()))::type;
205207

206208
public:
207209
template <utils::ConstexprString fieldName>
208-
inline constexpr auto& With(FieldConfig<impl::kFieldTypeOnIndex<T, impl::getFieldIndexByName<T>(fieldName)>>&& fieldConfig) {
210+
inline constexpr auto& With(FieldConfig<impl::kFieldTypeOnIndex<T, impl::getFieldIndexByName<T>(fieldName)>>&& field_config) {
209211
constexpr auto Index = impl::getFieldIndexByName<T>(fieldName);
210212
static_assert(Index != boost::pfr::tuple_size_v<T>, "Field Not Found");
211-
std::get<Index>(this->fieldsConfig) = std::move(fieldConfig);
213+
std::get<Index>(this->fields_config) = std::move(field_config);
212214
return *this;
213215
}
214-
constexpr SerializationConfig() : fieldsConfig({}) {}
216+
inline constexpr SerializationConfig() = default;
215217

216218
template <std::size_t I>
217-
constexpr auto Get() const {
218-
return std::get<I>(this->fieldsConfig);
219+
inline constexpr auto Get() const {
220+
return std::get<I>(this->fields_config);
219221
}
220222
private:
221-
kFieldsConfigType fieldsConfig;
222-
223+
FieldsConfigType fields_config = {};
223224
};
224225

226+
template <typename... Ts>
227+
class SerializationConfig<std::variant<Ts...>> {
228+
public:
229+
template <std::size_t I>
230+
inline constexpr auto& With(FieldConfig<decltype(Get<I>(utils::impl::TypeList<Ts...>{}))>&& field_config) {
231+
std::get<I>(this->variant_config) = std::move(field_config);
232+
return *this;
233+
}
234+
template <typename T>
235+
inline constexpr auto& With(FieldConfig<T>&& field_config) {
236+
return this->With<Find<T>(utils::impl::TypeList<Ts...>{})>(std::move(field_config));
237+
}
238+
private:
239+
std::tuple<FieldConfig<Ts>...> variant_config;
240+
};
225241

226242

227243
} // namespace formats::universal

universal/include/userver/utils/impl/type_list.hpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22
#include <type_traits>
3-
3+
#include <utility>
44

55
USERVER_NAMESPACE_BEGIN
66

@@ -11,13 +11,12 @@ struct TypeList {};
1111

1212

1313
template <typename... Ts>
14-
consteval auto size(TypeList<Ts...>) {
14+
consteval auto Size(TypeList<Ts...>) {
1515
return sizeof...(Ts);
1616
}
1717

18-
1918
template <template <typename...> typename Check, typename... Ts>
20-
consteval auto anyOf(TypeList<Ts...>) {
19+
consteval auto AnyOf(TypeList<Ts...>) {
2120
return (Check<Ts>::value || ...);
2221
}
2322

@@ -40,6 +39,19 @@ consteval auto IsConvertableCarried() {
4039
};
4140
}
4241

42+
struct Caster {
43+
inline constexpr Caster(auto) {}
44+
inline constexpr Caster() = default;
45+
};
46+
47+
template <std::size_t... Is, typename T>
48+
consteval auto Get(std::index_sequence<Is...>, decltype(Is, Caster())..., T&& arg, ...) -> T;
49+
50+
template <std::size_t I, typename... Ts>
51+
consteval auto Get(const TypeList<Ts...>&) -> decltype(Get(std::make_index_sequence<I>(), std::declval<Ts>()...));
52+
53+
54+
4355
} // namespace utils::impl
4456

4557
USERVER_NAMESPACE_END

universal/src/formats/json/universal_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct SomeStruct3 {
8282
template <>
8383
inline constexpr auto formats::universal::kSerialization<SomeStruct3> =
8484
SerializationConfig<SomeStruct3>()
85-
.With<"field">({.Additional = true});
85+
.With<"field">({.AdditionalProperties = true});
8686

8787
TEST(Serialize, Additional) {
8888
std::unordered_map<std::string, int> value;

0 commit comments

Comments
 (0)