diff options
author | kmokrov <kmokrov@yandex-team.com> | 2023-10-17 11:20:12 +0300 |
---|---|---|
committer | kmokrov <kmokrov@yandex-team.com> | 2023-10-17 12:14:22 +0300 |
commit | a74d8d38bfdad3260f263cbccf768589e16acfbb (patch) | |
tree | 17c5821a519ae5c760df3c40e9bbd0edcf87812e | |
parent | cf8a166dfde05806be6e1881e52f38757b70fbb0 (diff) | |
download | ydb-a74d8d38bfdad3260f263cbccf768589e16acfbb.tar.gz |
YTORM-214: Add parsing enum from yson integer
-rw-r--r-- | library/cpp/yt/misc/cast-inl.h | 26 | ||||
-rw-r--r-- | yt/yt/core/ytree/serialize-inl.h | 16 |
2 files changed, 36 insertions, 6 deletions
diff --git a/library/cpp/yt/misc/cast-inl.h b/library/cpp/yt/misc/cast-inl.h index a8b34c8af3..71049a4748 100644 --- a/library/cpp/yt/misc/cast-inl.h +++ b/library/cpp/yt/misc/cast-inl.h @@ -7,6 +7,7 @@ #include <util/string/cast.h> #include <util/string/printf.h> +#include <concepts> #include <type_traits> namespace NYT { @@ -16,29 +17,40 @@ namespace NYT { namespace NDetail { template <class T, class S> -typename std::enable_if<std::is_signed<T>::value && std::is_signed<S>::value, bool>::type IsInIntegralRange(S value) +bool IsInIntegralRange(S value) + requires std::is_signed_v<T> && std::is_signed_v<S> { return value >= std::numeric_limits<T>::min() && value <= std::numeric_limits<T>::max(); } template <class T, class S> -static typename std::enable_if<std::is_signed<T>::value && std::is_unsigned<S>::value, bool>::type IsInIntegralRange(S value) +bool IsInIntegralRange(S value) + requires std::is_signed_v<T> && std::is_unsigned_v<S> { return value <= static_cast<typename std::make_unsigned<T>::type>(std::numeric_limits<T>::max()); } template <class T, class S> -static typename std::enable_if<std::is_unsigned<T>::value && std::is_signed<S>::value, bool>::type IsInIntegralRange(S value) +bool IsInIntegralRange(S value) + requires std::is_unsigned_v<T> && std::is_signed_v<S> { return value >= 0 && static_cast<typename std::make_unsigned<S>::type>(value) <= std::numeric_limits<T>::max(); } template <class T, class S> -typename std::enable_if<std::is_unsigned<T>::value && std::is_unsigned<S>::value, bool>::type IsInIntegralRange(S value) +bool IsInIntegralRange(S value) + requires std::is_unsigned_v<T> && std::is_unsigned_v<S> { return value <= std::numeric_limits<T>::max(); } +template <class T, class S> +bool IsInIntegralRange(S value) + requires std::is_enum_v<S> +{ + return IsInIntegralRange<T>(static_cast<std::underlying_type_t<S>>(value)); +} + template <class T> TString FormatInvalidCastValue(T value) { @@ -88,7 +100,11 @@ T CheckedIntegralCast(S value) template <class T, class S> bool TryEnumCast(S value, T* result) { - auto candidate = static_cast<T>(value); + std::underlying_type_t<T> underlying; + if (!TryIntegralCast<std::underlying_type_t<T>>(value, &underlying)) { + return false; + } + auto candidate = static_cast<T>(underlying); if (!TEnumTraits<T>::FindLiteralByValue(candidate)) { return false; } diff --git a/yt/yt/core/ytree/serialize-inl.h b/yt/yt/core/ytree/serialize-inl.h index 78f31e7ff0..c33f96985e 100644 --- a/yt/yt/core/ytree/serialize-inl.h +++ b/yt/yt/core/ytree/serialize-inl.h @@ -14,6 +14,8 @@ #include <yt/yt/core/yson/protobuf_interop.h> #include <yt/yt/core/yson/pull_parser_deserialize.h> +#include <library/cpp/yt/misc/cast.h> + #include <optional> #include <numeric> @@ -505,7 +507,19 @@ void Deserialize(T& value, INodePtr node) node->GetType()); } } else { - value = ParseEnum<T>(node->GetValue<TString>()); + switch (node->GetType()) { + case ENodeType::String: { + value = ParseEnum<T>(node->GetValue<TString>()); + break; + } + case ENodeType::Int64: { + value = CheckedEnumCast<T>(node->AsInt64()->GetValue()); + break; + } + default: + THROW_ERROR_EXCEPTION("Cannot deserialize enum from %Qlv node", + node->GetType()); + } } } |