-
Notifications
You must be signed in to change notification settings - Fork 350
feat formats: automatic serialization/deserialization based on Boost.PFR #472
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 7 commits
82003c1
b49d32c
f1260f2
cf62dc4
ebb0d3e
d3a97d4
aee757f
8986d53
8e942ae
30b890b
c3323b9
1af8915
fc62f92
30a7b78
4c2bd65
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| #pragma once | ||
| #include <type_traits> | ||
| #include <string> | ||
| #include <cstdint> | ||
| #include <limits> | ||
| #include <userver/formats/parse/to.hpp> | ||
| #include <userver/utils/meta.hpp> | ||
| #include <userver/utils/impl/type_list.hpp> | ||
| #include <userver/formats/common/meta.hpp> | ||
| #include <userver/formats/parse/common_containers.hpp> | ||
|
|
||
|
|
||
| USERVER_NAMESPACE_BEGIN | ||
|
|
||
| namespace formats::parse { | ||
|
|
||
| namespace impl { | ||
|
|
||
| template <typename T, typename Value> | ||
| constexpr inline bool Is(Value&& value) { | ||
| if constexpr(std::is_same_v<T, bool>) { | ||
| return value.IsBool(); | ||
| } else if constexpr(meta::kIsInteger<T>) { | ||
| return (std::is_unsigned_v<T> && sizeof(T) == sizeof(std::uint64_t)) ? value.IsUInt64() : value.IsInt64(); | ||
| } else if constexpr(std::is_convertible_v<T, std::string>) { | ||
| return value.IsString(); | ||
| } else if constexpr(std::is_convertible_v<T, double>) { | ||
| return value.IsDouble(); | ||
| } else if constexpr(meta::kIsRange<T>) { | ||
| return value.IsArray(); | ||
| } else { | ||
| return value.IsObject(); | ||
| } | ||
| } | ||
| bool CheckInBounds(const auto& x, const auto& min, const auto& max) { | ||
| if (x < min || x > max) { | ||
| return false; | ||
| }; | ||
| return true; | ||
|
Comment on lines
+19
to
+22
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can simplified. The other changes may (or may not) render this comment obsolete, though
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| }; | ||
| inline constexpr utils::impl::TypeList<bool, double, std::string> kBaseTypes; | ||
|
|
||
| } // namespace impl | ||
|
|
||
|
|
||
| template <typename T, typename Value> | ||
| constexpr inline std::enable_if_t< | ||
| utils::impl::AnyOf(utils::impl::IsSameCarried<T>(), impl::kBaseTypes) || | ||
| meta::kIsInteger<T>, std::optional<T>> | ||
| TryParse(Value&& value, userver::formats::parse::To<T>) { | ||
linuxnyasha marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if(!impl::Is<T>(value)) { | ||
| return std::nullopt; | ||
| } | ||
| return value.template As<T>(); | ||
| } | ||
|
|
||
| template <typename T, typename Value> | ||
| constexpr inline std::optional<std::optional<T>> TryParse(Value&& value, userver::formats::parse::To<std::optional<T>>) { | ||
| return TryParse(std::forward<Value>(value), userver::formats::parse::To<T>{}); | ||
linuxnyasha marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| template <typename Value> | ||
| constexpr inline std::optional<float> TryParse(Value&& value, userver::formats::parse::To<float>) { | ||
| auto response = value.template As<double>(); | ||
| if(impl::CheckInBounds(response, std::numeric_limits<float>::lowest(), | ||
| std::numeric_limits<float>::max())) { | ||
| return static_cast<float>(response); | ||
| }; | ||
| return std::nullopt; | ||
| }; | ||
|
|
||
| template <typename T, typename Value> | ||
| constexpr inline std::enable_if_t<meta::kIsRange<T> && !meta::kIsMap<T> && | ||
| !std::is_same_v<T, boost::uuids::uuid> && | ||
| !utils::impl::AnyOf(utils::impl::IsConvertableCarried<T>(), impl::kBaseTypes) && | ||
|
||
| !std::is_convertible_v< | ||
| T&, utils::impl::strong_typedef::StrongTypedefTag&>, | ||
| std::optional<T>> | ||
| TryParse(Value&& from, To<T>) { | ||
| T response; | ||
| auto inserter = std::inserter(response, response.end()); | ||
| using ValueType = meta::RangeValueType<T>; | ||
| for(const auto& item : from) { | ||
| auto insert = TryParse(item, userver::formats::parse::To<ValueType>{}); | ||
| if(!insert) { | ||
| return std::nullopt; | ||
| }; | ||
| *inserter = *insert; | ||
Anton3 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ++inserter; | ||
| }; | ||
| return response; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| } // namespace formats::parse | ||
|
|
||
| USERVER_NAMESPACE_END | ||
Uh oh!
There was an error while loading. Please reload this page.