@@ -15,51 +15,68 @@ 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
4527
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)) {
28+ template <typename Value>
29+ inline constexpr std::optional<bool > TryParse (Value&& value, To<bool >) {
30+ if (!value.IsBool ()) {
31+ return std::nullopt ;
32+ }
33+ return value.template As <bool >();
34+ }
35+ template <typename Value>
36+ inline constexpr std::optional<double > TryParse (Value&& value, To<double >) {
37+ if (!value.IsDouble ()) {
38+ return std::nullopt ;
39+ }
40+ return value.template As <double >();
41+ }
42+ template <typename Value>
43+ inline constexpr std::optional<std::string> TryParse (Value&& value, To<std::string>) {
44+ if (!value.IsString ()) {
45+ return std::nullopt ;
46+ }
47+ return value.template As <std::string>();
48+ }
49+
50+ template <typename Value, typename T>
51+ inline constexpr std::optional<T> TryParse (Value&& value, To<T>) requires meta::kIsInteger<T> {
52+ if ((std::is_unsigned_v<T> && sizeof (T) == sizeof (std::uint64_t )) ? value.IsUInt64 () : value.IsInt64 ()) {
5253 return std::nullopt ;
5354 }
5455 return value.template As <T>();
5556}
57+ template <typename Value, typename T>
58+ inline constexpr std::optional<std::vector<T>> TryParse (Value&& value, To<std::vector<T>>) {
59+ if (!value.IsArray ()) {
60+ return std::nullopt ;
61+ }
62+ std::vector<T> response;
63+ response.reserve (value.GetSize ());
64+ for (const auto & item : value) {
65+ auto insert = TryParse (item, To<T>{});
66+ if (!insert) {
67+ return std::nullopt ;
68+ }
69+ response.insert (std::move (*insert));
70+ }
71+ return value.template As <std::vector<T>>();
72+ }
5673
5774template <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>{});
75+ constexpr inline std::optional<std::optional<T>> TryParse (Value&& value, To<std::optional<T>>) {
76+ return TryParse (std::forward<Value>(value), To<T>{});
6077}
6178template <typename Value>
62- constexpr inline std::optional<float > TryParse (Value&& value, userver::formats::parse:: To<float >) {
79+ constexpr inline std::optional<float > TryParse (Value&& value, To<float >) {
6380 auto response = value.template As <double >();
6481 if (impl::CheckInBounds (response, std::numeric_limits<float >::lowest (),
6582 std::numeric_limits<float >::max ())) {
@@ -68,29 +85,6 @@ constexpr inline std::optional<float> TryParse(Value&& value, userver::formats::
6885 return std::nullopt ;
6986};
7087
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;
91- }
92-
93-
9488
9589} // namespace formats::parse
9690
0 commit comments