@@ -15,79 +15,81 @@ USERVER_NAMESPACE_BEGIN
1515namespace formats ::parse {
1616
1717namespace impl {
18-
19- template <typename T, typename Value>
20- constexpr inline bool Is (Value&& value) {
21- if constexpr (std::is_same_v<T, bool >) {
22- return value.IsBool ();
23- } else if constexpr (meta::kIsInteger <T>) {
24- return (std::is_unsigned_v<T> && sizeof (T) == sizeof (std::uint64_t )) ? value.IsUInt64 () : value.IsInt64 ();
25- } else if constexpr (std::is_convertible_v<T, std::string>) {
26- return value.IsString ();
27- } else if constexpr (std::is_convertible_v<T, double >) {
28- return value.IsDouble ();
29- } else if constexpr (meta::kIsRange <T>) {
30- return value.IsArray ();
31- } else {
32- return value.IsObject ();
33- }
34- }
3518bool CheckInBounds (const auto & x, const auto & min, const auto & max) {
3619 if (x < min || x > max) {
3720 return false ;
3821 };
3922 return true ;
4023};
41- inline constexpr utils::impl::TypeList<bool , double , std::string> kBaseTypes ;
4224
4325} // namespace impl
4426
27+ template <typename Value, typename T>
28+ inline constexpr std::optional<T> TryParse (Value&& value, To<T>) {
29+ if (!value.IsObject ()) {
30+ return std::nullopt ;
31+ }
32+ return value.template As <T>();
33+ }
4534
46- template <typename T, typename Value>
47- constexpr inline std::enable_if_t <
48- utils::impl::AnyOf (utils::impl::IsSameCarried<T>(), impl::kBaseTypes ) ||
49- meta::kIsInteger <T>, std::optional<T>>
50- TryParse (Value&& value, userver::formats::parse::To<T>) {
51- if (!impl::Is<T>(value)) {
35+ template <typename Value>
36+ inline constexpr std::optional<bool > TryParse (Value&& value, To<bool >) {
37+ if (!value.IsBool ()) {
38+ return std::nullopt ;
39+ }
40+ return value.template As <bool >();
41+ }
42+ template <typename Value>
43+ inline constexpr std::optional<double > TryParse (Value&& value, To<double >) {
44+ if (!value.IsDouble ()) {
45+ return std::nullopt ;
46+ }
47+ return value.template As <double >();
48+ }
49+ template <typename Value>
50+ inline constexpr std::optional<std::string> TryParse (Value&& value, To<std::string>) {
51+ if (!value.IsString ()) {
52+ return std::nullopt ;
53+ }
54+ return value.template As <std::string>();
55+ }
56+
57+ template <typename Value, typename T>
58+ inline constexpr std::optional<T> TryParse (Value&& value, To<T>) requires meta::kIsInteger<T> {
59+ if (!((std::is_unsigned_v<T> && sizeof (T) == sizeof (std::uint64_t )) ? value.IsUInt64 () : value.IsInt64 ())) {
5260 return std::nullopt ;
5361 }
5462 return value.template As <T>();
5563}
64+ template <typename Value, typename T>
65+ inline constexpr std::optional<std::vector<T>> TryParse (Value&& value, To<std::vector<T>>) {
66+ if (!value.IsArray ()) {
67+ return std::nullopt ;
68+ }
69+ std::vector<T> response;
70+ response.reserve (value.GetSize ());
71+ for (const auto & item : value) {
72+ auto insert = TryParse (item, To<T>{});
73+ if (!insert) {
74+ return std::nullopt ;
75+ }
76+ response.push_back (std::move (*insert));
77+ }
78+ return response;
79+ }
5680
5781template <typename T, typename Value>
58- constexpr inline std::optional<std::optional<T>> TryParse (Value&& value, userver::formats::parse:: To<std::optional<T>>) {
59- return TryParse (std::forward<Value>(value), userver::formats::parse:: To<T>{});
82+ constexpr inline std::optional<std::optional<T>> TryParse (Value&& value, To<std::optional<T>>) {
83+ return TryParse (std::forward<Value>(value), To<T>{});
6084}
6185template <typename Value>
62- constexpr inline std::optional<float > TryParse (Value&& value, userver::formats::parse:: To<float >) {
86+ constexpr inline std::optional<float > TryParse (Value&& value, To<float >) {
6387 auto response = value.template As <double >();
6488 if (impl::CheckInBounds (response, std::numeric_limits<float >::lowest (),
6589 std::numeric_limits<float >::max ())) {
6690 return static_cast <float >(response);
67- };
91+ }
6892 return std::nullopt ;
69- };
70-
71- template <typename T, typename Value>
72- constexpr inline std::enable_if_t <meta::kIsRange <T> && !meta::kIsMap <T> &&
73- !std::is_same_v<T, boost::uuids::uuid> &&
74- !utils::impl::AnyOf(utils::impl::IsConvertableCarried<T>(), impl::kBaseTypes ) &&
75- !std::is_convertible_v<
76- T&, utils::impl::strong_typedef::StrongTypedefTag&>,
77- std::optional<T>>
78- TryParse (Value&& from, To<T>) {
79- T response;
80- auto inserter = std::inserter (response, response.end ());
81- using ValueType = meta::RangeValueType<T>;
82- for (const auto & item : from) {
83- auto insert = TryParse (item, userver::formats::parse::To<ValueType>{});
84- if (!insert) {
85- return std::nullopt ;
86- };
87- *inserter = *insert;
88- ++inserter;
89- };
90- return response;
9193}
9294
9395
0 commit comments