Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
linuxnyasha committed Mar 11, 2024
1 parent 30b890b commit 5703876
Showing 1 changed file with 44 additions and 50 deletions.
94 changes: 44 additions & 50 deletions universal/include/userver/formats/parse/try_parse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,51 +15,68 @@ 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;
};
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>) {
if(!impl::Is<T>(value)) {
template <typename Value>
inline constexpr std::optional<bool> TryParse(Value&& value, To<bool>) {
if(!value.IsBool()) {
return std::nullopt;
}
return value.template As<bool>();
}
template <typename Value>
inline constexpr std::optional<double> TryParse(Value&& value, To<double>) {
if(!value.IsDouble()) {
return std::nullopt;
}
return value.template As<double>();
}
template <typename Value>
inline constexpr std::optional<std::string> TryParse(Value&& value, To<std::string>) {
if(!value.IsString()) {
return std::nullopt;
}
return value.template As<std::string>();
}

template <typename Value, typename T>
inline constexpr std::optional<T> TryParse(Value&& value, To<T>) requires meta::kIsInteger<T> {
if((std::is_unsigned_v<T> && sizeof(T) == sizeof(std::uint64_t)) ? value.IsUInt64() : value.IsInt64()) {
return std::nullopt;
}
return value.template As<T>();
}
template <typename Value, typename T>
inline constexpr std::optional<std::vector<T>> TryParse(Value&& value, To<std::vector<T>>) {
if(!value.IsArray()) {
return std::nullopt;
}
std::vector<T> response;
response.reserve(value.GetSize());
for(const auto& item : value) {
auto insert = TryParse(item, To<T>{});
if(!insert) {
return std::nullopt;
}
response.insert(std::move(*insert));
}
return value.template As<std::vector<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>{});
constexpr inline std::optional<std::optional<T>> TryParse(Value&& value, To<std::optional<T>>) {
return TryParse(std::forward<Value>(value), To<T>{});
}
template <typename Value>
constexpr inline std::optional<float> TryParse(Value&& value, userver::formats::parse::To<float>) {
constexpr inline std::optional<float> TryParse(Value&& value, To<float>) {
auto response = value.template As<double>();
if(impl::CheckInBounds(response, std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::max())) {
Expand All @@ -68,29 +85,6 @@ constexpr inline std::optional<float> TryParse(Value&& value, userver::formats::
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;
++inserter;
};
return response;
}



} // namespace formats::parse

Expand Down

0 comments on commit 5703876

Please sign in to comment.