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>
1315USERVER_NAMESPACE_BEGIN
1416namespace 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
2724template <typename ... T>
2825struct Configurator {};
@@ -31,7 +28,15 @@ struct Additional;
3128
3229template <auto >
3330struct 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
3641template <auto Needed, auto Value, typename T, typename F>
3742consteval auto TransformIfEqual (const T& obj, const F& f) {
@@ -112,7 +117,7 @@ constexpr inline Field Read(Value&& value, parse::To<Field>) {
112117
113118template <typename T, auto I, typename ... Params, typename From, typename Value>
114119constexpr 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>>
116121Read (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
127132template <typename T, auto I, typename ... Params, typename From, typename Value>
128133constexpr 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>>>
130135Read (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
135140constexpr 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
141149template <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+
155164template <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 >
157166RunWrite (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
163172template <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
166175template <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
169178template <typename T, auto I, typename Builder, typename Field, typename CheckT>
170179constexpr 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+
201220template <typename T, auto I, typename Format, typename ... Params>
202221constexpr inline std::optional<std::remove_cvref_t <decltype (boost::pfr::get<I>(std::declval<T>()))>>
203222UniversalTryParseField (
@@ -209,33 +228,20 @@ UniversalTryParseField(
209228
210229
211230 auto val = Read<T, I, Params...>(from, userver::formats::parse::To<std::optional<FieldType>>{});
212- if (val && (Check (* val, Params{}) && ...)) {
231+ if ((Check (val, Params{}) && ...)) {
213232 return val;
214233 };
215234 return std::nullopt ;
216235};
217236
218- } // namespace detail
237+ } // namespace impl
219238
220239template <typename T, typename ... Params>
221240class 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-
235241 public:
236242 static consteval auto Create () {
237243 return []<auto ... I>(std::index_sequence<I...>){
238- return SerializationConfig<T, detail ::FieldParametries<T, I>...>{};
244+ return SerializationConfig<T, impl ::FieldParametries<T, I>...>{};
239245 }(std::make_index_sequence<boost::pfr::tuple_size_v<T>>());
240246 };
241247
@@ -277,6 +283,20 @@ class SerializationConfig {
277283 constexpr SerializationConfig () noexcept {
278284 static_assert (sizeof ...(Params) == boost::pfr::tuple_size_v<T>, " Use Create" );
279285 };
286+ private:
287+ template <auto I, typename Param>
288+ static consteval auto AddParamTo () {
289+ return []<auto ... Is>(std::index_sequence<Is...>){
290+ return SerializationConfig<T, decltype (
291+ impl::TransformIfEqual<I, Is>(Params{},
292+ []<typename ... FieldParams>(impl::FieldParametries<T, I, FieldParams...>){
293+ return impl::FieldParametries<T, I, FieldParams..., Param>();
294+ })
295+ )...>();
296+ }(std::make_index_sequence<sizeof ...(Params)>());
297+ };
298+
299+
280300};
281301
282302
@@ -285,25 +305,25 @@ namespace formats::parse {
285305
286306template <typename Format, typename T>
287307constexpr inline
288- std::enable_if_t <!std::is_same_v<decltype (universal::kDeserialization <std::remove_cvref_t <T>>), const universal::detail ::Disabled>, T>
308+ std::enable_if_t <!std::is_same_v<decltype (universal::kDeserialization <std::remove_cvref_t <T>>), const universal::impl ::Disabled>, T>
289309Parse (Format&& from,
290310 To<T>) {
291311 using Config = std::remove_const_t <decltype (universal::kDeserialization <std::remove_cvref_t <T>>)>;
292312 using Type = std::remove_cvref_t <T>;
293313 return [from = std::forward<Format>(from)]<typename ... Params>(universal::SerializationConfig<Type, Params...>){
294- return T{universal::detail ::UniversalParseField (Params{}, std::forward<Format>(from))...};
314+ return T{universal::impl ::UniversalParseField (Params{}, std::forward<Format>(from))...};
295315 }(Config{});
296316};
297317
298318template <typename Format, typename T>
299319constexpr 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>>
320+ std::enable_if_t <!std::is_same_v<decltype (universal::kDeserialization <std::remove_cvref_t <T>>), const universal::impl ::Disabled>, std::optional<T>>
301321TryParse (Format&& from,
302322 To<T>) {
303323 using Config = std::remove_const_t <decltype (universal::kDeserialization <std::remove_cvref_t <T>>)>;
304324 using Type = std::remove_cvref_t <T>;
305325 return [&]<typename ... Params>(universal::SerializationConfig<Type, Params...>) -> std::optional<T> {
306- auto fields = std::make_tuple (universal::detail ::UniversalTryParseField (Params{}, from)...);
326+ auto fields = std::make_tuple (universal::impl ::UniversalTryParseField (Params{}, from)...);
307327 constexpr auto fieldsCount = boost::pfr::tuple_size_v<T>;
308328 if ([&]<auto ... I>(std::index_sequence<I...>){
309329 return (std::get<I>(fields) && ...);
0 commit comments