Skip to content

Commit 0784a5f

Browse files
committed
Fixes
1 parent 98cbcd5 commit 0784a5f

File tree

11 files changed

+151
-111
lines changed

11 files changed

+151
-111
lines changed

universal/include/userver/formats/json.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <userver/formats/json/serialize.hpp>
1111
#include <userver/formats/json/value.hpp>
1212
#include <userver/formats/json/value_builder.hpp>
13-
#include <userver/formats/json/universal.hpp>
1413

1514
USERVER_NAMESPACE_BEGIN
1615

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ namespace formats::json {
99

1010
template <typename T>
1111
inline constexpr
12-
std::enable_if_t<!std::is_same_v<decltype(universal::kSerialization<std::remove_cvref_t<T>>), const universal::detail::Disabled>, Value>
12+
std::enable_if_t<!std::is_same_v<decltype(universal::kSerialization<std::remove_cvref_t<T>>), const universal::impl::Disabled>, Value>
1313
Serialize(T&& obj,
1414
serialize::To<Value>) {
1515
using Config = std::remove_const_t<decltype(universal::kSerialization<std::remove_cvref_t<T>>)>;
1616
using Type = std::remove_cvref_t<T>;
1717
return [&]<typename... Params>
1818
(universal::SerializationConfig<Type, Params...>){
1919
ValueBuilder builder;
20-
(universal::detail::UniversalSerializeField(Params{}, builder, obj), ...);
20+
(universal::impl::UniversalSerializeField(Params{}, builder, obj), ...);
2121
return builder.ExtractValue();
2222
}(Config{});
2323
};

universal/include/userver/formats/parse/common.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include <userver/utils/datetime/from_string_saturating.hpp>
1919
#include <userver/utils/meta.hpp>
2020
#include <userver/utils/string_to_duration.hpp>
21-
#include <userver/formats/parse/try_parse.hpp>
2221

2322
USERVER_NAMESPACE_BEGIN
2423

universal/include/userver/formats/parse/try_parse.hpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <cstdint>
55
#include <userver/formats/parse/to.hpp>
66
#include <userver/utils/meta.hpp>
7-
#include <userver/utils/type_list.hpp>
7+
#include <userver/utils/impl/type_list.hpp>
88
#include <userver/formats/common/meta.hpp>
99

1010
USERVER_NAMESPACE_BEGIN
@@ -14,7 +14,7 @@ namespace formats::parse {
1414
namespace impl {
1515

1616
template <typename T, typename Value>
17-
inline bool Is(Value&& value) {
17+
constexpr inline bool Is(Value&& value) {
1818
if constexpr(std::is_convertible_v<T, std::int64_t>) {
1919
return value.IsInt();
2020
} else if constexpr(std::is_convertible_v<T, std::string>) {
@@ -28,25 +28,33 @@ inline bool Is(Value&& value) {
2828
}
2929
}
3030

31-
inline constexpr utils::TypeList<bool, int, std::int64_t, std::uint64_t, double, std::string> kBaseTypes;
31+
inline constexpr utils::impl::TypeList<bool, std::int64_t, std::uint64_t, double, std::string> kBaseTypes;
3232

3333

3434
} // namespace impl
3535

3636

3737
template <typename T, typename Value>
38-
inline std::enable_if_t<utils::AnyOf(utils::IsSameCarried<T>(), impl::kBaseTypes), std::optional<T>>
38+
constexpr inline std::enable_if_t<utils::impl::AnyOf(utils::impl::IsConvertableCarried<T>(), impl::kBaseTypes), std::optional<T>>
3939
TryParse(Value&& value, userver::formats::parse::To<T>) {
40-
if(value.IsMissing() || value.IsNull() || !impl::Is<T>(value)) {
40+
if(!impl::Is<T>(value)) {
4141
return std::nullopt;
4242
}
43-
return value.template As<T>();
43+
auto obj = value.template As<std::optional<T>>();
44+
if(obj) {
45+
return obj;
46+
}
47+
return std::nullopt;
4448
}
4549

4650
template <typename T, typename Value>
47-
inline std::optional<T> TryParse(Value&& value, userver::formats::parse::To<std::optional<T>>) {
48-
return TryParse(std::forward<Value>(value), userver::formats::parse::To<T>{});
49-
};
51+
constexpr inline std::optional<std::optional<T>> TryParse(Value&& value, userver::formats::parse::To<std::optional<T>>) {
52+
auto object = TryParse(std::forward<Value>(value), userver::formats::parse::To<T>{});
53+
if(object) {
54+
return object;
55+
}
56+
return std::nullopt;
57+
}
5058

5159
} // namespace formats::parse
5260

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
USERVER_NAMESPACE_BEGIN
99
namespace formats::universal {
1010

11+
1112
template <auto Value>
1213
struct Min {
1314
static constexpr auto kValue = Value;
@@ -31,12 +32,14 @@ struct Pattern {
3132
struct Additional {};
3233

3334
template <typename Field, auto Value>
34-
constexpr inline auto Check(const Field& field, Max<Value>) noexcept {
35+
constexpr inline std::enable_if_t<!meta::kIsOptional<Field>, bool>
36+
Check(const Field& field, Max<Value>) noexcept {
3537
return Value >= field;
3638
};
3739

3840
template <typename Field, auto Value>
39-
constexpr inline auto Check(const Field& field, Min<Value>) noexcept {
41+
constexpr inline std::enable_if_t<!meta::kIsOptional<Field>, bool>
42+
Check(const Field& field, Min<Value>) noexcept {
4043
return field >= Value;
4144
};
4245

@@ -59,7 +62,9 @@ constexpr inline auto Check(const std::optional<Field>&, Default<Value>) noexcep
5962
};
6063

6164
template <typename Field>
62-
constexpr inline auto Check(const Field&, Additional) noexcept {
65+
constexpr inline
66+
std::enable_if_t<!meta::kIsOptional<Field>, bool>
67+
Check(const Field&, Additional) noexcept {
6368
return true;
6469
};
6570

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

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#pragma once
2-
#include <userver/utils/type_list.hpp>
3-
#include <userver/utils/string.hpp>
2+
#include <userver/utils/impl/type_list.hpp>
3+
#include <userver/utils/constexpr_string.hpp>
44
#include <userver/formats/parse/to.hpp>
5+
#include <userver/formats/parse/try_parse.hpp>
6+
#include <userver/formats/parse/common_containers.hpp>
57
#include <userver/formats/serialize/to.hpp>
68
#include <userver/formats/common/meta.hpp>
79
#include <userver/formats/common/items.hpp>
@@ -13,16 +15,11 @@
1315
USERVER_NAMESPACE_BEGIN
1416
namespace formats::universal {
1517

16-
namespace detail {
17-
struct Disabled {};
18-
} //namespace detail
19-
20-
template <typename T>
21-
inline static constexpr auto kSerialization = detail::Disabled{};
18+
namespace impl {
2219

23-
template <typename T>
24-
inline static constexpr auto kDeserialization = kSerialization<T>;
20+
struct Disabled {};
2521

22+
} //namespace impl
2623

2724
template <typename... T>
2825
struct Configurator {};
@@ -31,7 +28,15 @@ struct Additional;
3128

3229
template <auto>
3330
struct Default;
34-
namespace detail {
31+
32+
33+
template <typename T>
34+
inline static constexpr auto kSerialization = impl::Disabled{};
35+
36+
template <typename T>
37+
inline static constexpr auto kDeserialization = kSerialization<T>;
38+
39+
namespace impl {
3540

3641
template <auto Needed, auto Value, typename T, typename F>
3742
consteval auto TransformIfEqual(const T& obj, const F& f) {
@@ -112,7 +117,7 @@ constexpr inline Field Read(Value&& value, parse::To<Field>) {
112117

113118
template <typename T, auto I, typename... Params, typename From, typename Value>
114119
constexpr inline
115-
std::enable_if_t<utils::AnyOf(utils::IsSameCarried<Additional>(), utils::TypeList<Params...>{}), std::unordered_map<std::string, Value>>
120+
std::enable_if_t<utils::impl::AnyOf(utils::impl::IsSameCarried<Additional>(), utils::impl::TypeList<Params...>{}), std::unordered_map<std::string, Value>>
116121
Read(const From& value, parse::To<std::unordered_map<std::string, Value>>) {
117122
constexpr auto names = boost::pfr::names_as_array<T>();
118123
std::unordered_map<std::string, Value> result;
@@ -126,7 +131,7 @@ Read(const From& value, parse::To<std::unordered_map<std::string, Value>>) {
126131

127132
template <typename T, auto I, typename... Params, typename From, typename Value>
128133
constexpr inline
129-
std::enable_if_t<utils::AnyOf(utils::IsSameCarried<Additional>(), utils::TypeList<Params...>{}), std::optional<std::unordered_map<std::string, Value>>>
134+
std::enable_if_t<utils::impl::AnyOf(utils::impl::IsSameCarried<Additional>(), utils::impl::TypeList<Params...>{}), std::optional<std::unordered_map<std::string, Value>>>
130135
Read(const From& value, parse::To<std::optional<std::unordered_map<std::string, Value>>>) {
131136
return Read<T, I, Params...>(value, parse::To<std::unordered_map<std::string, Value>>{});
132137
};
@@ -135,7 +140,10 @@ template <typename T, auto I, typename... Params, typename Value, typename Field
135140
constexpr inline std::optional<Field> Read(Value&& value, parse::To<std::optional<Field>>) {
136141
using parse::TryParse;
137142
static_assert(common::impl::kHasTryParse<Value, Field>, "Not Found Try Parse");
138-
return TryParse(value[boost::pfr::get_name<I, T>()], parse::To<Field>{});
143+
return TryParse(value[boost::pfr::get_name<I, T>()], parse::To<Field>{}); };
144+
template <typename T, auto I, typename... Params, typename Value, typename Field>
145+
constexpr inline std::optional<Field> Read(Value&& value, parse::To<std::optional<std::optional<Field>>>) {
146+
return Read<T, I, Params...>(std::forward<Value>(value), parse::To<std::optional<Field>>{});
139147
};
140148

141149
template <typename T, auto I, typename Builder, typename Field, auto Value>
@@ -152,19 +160,20 @@ constexpr inline auto RunParseCheckFor(const Value&, std::optional<Field>& field
152160
};
153161
};
154162

163+
155164
template <typename T, auto I, typename... Params, typename Builder, typename Value>
156-
constexpr inline std::enable_if_t<utils::AnyOf(utils::IsSameCarried<Additional>(), utils::TypeList<Params...>{}), void>
165+
constexpr inline std::enable_if_t<utils::impl::AnyOf(utils::impl::IsSameCarried<Additional>(), utils::impl::TypeList<Params...>{}), void>
157166
RunWrite(Builder& builder, const std::unordered_map<std::string, Value>& field) {
158167
for(const auto& element : field) {
159168
builder[element.first] = element.second;
160169
};
161170
};
162171

163172
template <typename T, auto I, typename Builder, typename Field>
164-
constexpr inline auto RunCheckFor(Builder&, Field&&, detail::Disabled) noexcept {};
173+
constexpr inline auto RunCheckFor(Builder&, Field&&, Disabled) noexcept {};
165174

166175
template <typename T, auto I, typename Builder, typename Field>
167-
constexpr inline auto RunCheckFor(Builder&, const std::optional<Field>&, detail::Disabled) noexcept {};
176+
constexpr inline auto RunCheckFor(Builder&, const std::optional<Field>&, Disabled) noexcept {};
168177

169178
template <typename T, auto I, typename Builder, typename Field, typename CheckT>
170179
constexpr inline auto RunCheckFor(Builder&, Field&& field, CheckT check) {
@@ -198,6 +207,16 @@ constexpr inline auto UniversalParseField(
198207
return value;
199208
};
200209

210+
template <typename T>
211+
consteval bool AdditionalCheck(const T&) {
212+
return false;
213+
};
214+
215+
template <typename T>
216+
consteval bool AdditionalCheck(const std::optional<std::optional<T>>&) {
217+
return true;
218+
};
219+
201220
template <typename T, auto I, typename Format, typename... Params>
202221
constexpr inline std::optional<std::remove_cvref_t<decltype(boost::pfr::get<I>(std::declval<T>()))>>
203222
UniversalTryParseField(
@@ -209,33 +228,25 @@ UniversalTryParseField(
209228

210229

211230
auto val = Read<T, I, Params...>(from, userver::formats::parse::To<std::optional<FieldType>>{});
231+
if(!val) {
232+
if((Check(val, Params{}) && ...)) {
233+
return val;
234+
};
235+
};
212236
if(val && (Check(*val, Params{}) && ...)) {
213237
return val;
214238
};
215239
return std::nullopt;
216240
};
217241

218-
} // namespace detail
242+
} // namespace impl
219243

220244
template <typename T, typename... Params>
221245
class SerializationConfig {
222-
private:
223-
template <auto I, typename Param>
224-
static consteval auto AddParamTo() {
225-
return []<auto... Is>(std::index_sequence<Is...>){
226-
return SerializationConfig<T, decltype(
227-
detail::TransformIfEqual<I, Is>(Params{},
228-
[]<typename... FieldParams>(detail::FieldParametries<T, I, FieldParams...>){
229-
return detail::FieldParametries<T, I, FieldParams..., Param>();
230-
})
231-
)...>();
232-
}(std::make_index_sequence<sizeof...(Params)>());
233-
};
234-
235246
public:
236247
static consteval auto Create() {
237248
return []<auto... I>(std::index_sequence<I...>){
238-
return SerializationConfig<T, detail::FieldParametries<T, I>...>{};
249+
return SerializationConfig<T, impl::FieldParametries<T, I>...>{};
239250
}(std::make_index_sequence<boost::pfr::tuple_size_v<T>>());
240251
};
241252

@@ -277,6 +288,20 @@ class SerializationConfig {
277288
constexpr SerializationConfig() noexcept {
278289
static_assert(sizeof...(Params) == boost::pfr::tuple_size_v<T>, "Use Create");
279290
};
291+
private:
292+
template <auto I, typename Param>
293+
static consteval auto AddParamTo() {
294+
return []<auto... Is>(std::index_sequence<Is...>){
295+
return SerializationConfig<T, decltype(
296+
impl::TransformIfEqual<I, Is>(Params{},
297+
[]<typename... FieldParams>(impl::FieldParametries<T, I, FieldParams...>){
298+
return impl::FieldParametries<T, I, FieldParams..., Param>();
299+
})
300+
)...>();
301+
}(std::make_index_sequence<sizeof...(Params)>());
302+
};
303+
304+
280305
};
281306

282307

@@ -285,25 +310,25 @@ namespace formats::parse {
285310

286311
template <typename Format, typename T>
287312
constexpr inline
288-
std::enable_if_t<!std::is_same_v<decltype(universal::kDeserialization<std::remove_cvref_t<T>>), const universal::detail::Disabled>, T>
313+
std::enable_if_t<!std::is_same_v<decltype(universal::kDeserialization<std::remove_cvref_t<T>>), const universal::impl::Disabled>, T>
289314
Parse(Format&& from,
290315
To<T>) {
291316
using Config = std::remove_const_t<decltype(universal::kDeserialization<std::remove_cvref_t<T>>)>;
292317
using Type = std::remove_cvref_t<T>;
293318
return [from = std::forward<Format>(from)]<typename... Params>(universal::SerializationConfig<Type, Params...>){
294-
return T{universal::detail::UniversalParseField(Params{}, std::forward<Format>(from))...};
319+
return T{universal::impl::UniversalParseField(Params{}, std::forward<Format>(from))...};
295320
}(Config{});
296321
};
297322

298323
template <typename Format, typename T>
299324
constexpr inline
300-
std::enable_if_t<!std::is_same_v<decltype(universal::kDeserialization<std::remove_cvref_t<T>>), const universal::detail::Disabled>, std::optional<T>>
325+
std::enable_if_t<!std::is_same_v<decltype(universal::kDeserialization<std::remove_cvref_t<T>>), const universal::impl::Disabled>, std::optional<T>>
301326
TryParse(Format&& from,
302327
To<T>) {
303328
using Config = std::remove_const_t<decltype(universal::kDeserialization<std::remove_cvref_t<T>>)>;
304329
using Type = std::remove_cvref_t<T>;
305330
return [&]<typename... Params>(universal::SerializationConfig<Type, Params...>) -> std::optional<T> {
306-
auto fields = std::make_tuple(universal::detail::UniversalTryParseField(Params{}, from)...);
331+
auto fields = std::make_tuple(universal::impl::UniversalTryParseField(Params{}, from)...);
307332
constexpr auto fieldsCount = boost::pfr::tuple_size_v<T>;
308333
if([&]<auto... I>(std::index_sequence<I...>){
309334
return (std::get<I>(fields) && ...);

universal/include/userver/formats/yaml.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <userver/formats/yaml/types.hpp>
1111
#include <userver/formats/yaml/value.hpp>
1212
#include <userver/formats/yaml/value_builder.hpp>
13-
#include <userver/formats/yaml/universal.hpp>
1413

1514
USERVER_NAMESPACE_BEGIN
1615

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ namespace formats::yaml {
88

99
template <typename T>
1010
inline constexpr
11-
std::enable_if_t<!std::is_same_v<decltype(universal::kSerialization<std::remove_cvref_t<T>>), const universal::detail::Disabled>, Value>
11+
std::enable_if_t<!std::is_same_v<decltype(universal::kSerialization<std::remove_cvref_t<T>>), const universal::impl::Disabled>, Value>
1212
Serialize(T&& obj,
1313
serialize::To<Value>) {
1414
using Config = std::remove_const_t<decltype(universal::kSerialization<std::remove_cvref_t<T>>)>;
1515
using Type = std::remove_cvref_t<T>;
1616
return [&]<typename... Params>
1717
(universal::SerializationConfig<Type, Params...>){
1818
ValueBuilder builder;
19-
(universal::detail::UniversalSerializeField(Params{}, builder, obj), ...);
19+
(universal::impl::UniversalSerializeField(Params{}, builder, obj), ...);
2020
return builder.ExtractValue();
2121
}(Config{});
2222
};

0 commit comments

Comments
 (0)