aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmokrov <kmokrov@yandex-team.com>2023-10-17 11:20:12 +0300
committerkmokrov <kmokrov@yandex-team.com>2023-10-17 12:14:22 +0300
commita74d8d38bfdad3260f263cbccf768589e16acfbb (patch)
tree17c5821a519ae5c760df3c40e9bbd0edcf87812e
parentcf8a166dfde05806be6e1881e52f38757b70fbb0 (diff)
downloadydb-a74d8d38bfdad3260f263cbccf768589e16acfbb.tar.gz
YTORM-214: Add parsing enum from yson integer
-rw-r--r--library/cpp/yt/misc/cast-inl.h26
-rw-r--r--yt/yt/core/ytree/serialize-inl.h16
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());
+ }
}
}