summaryrefslogtreecommitdiffstats
path: root/library/cpp/yt
diff options
context:
space:
mode:
authorpechatnov <[email protected]>2026-03-26 10:11:59 +0300
committerpechatnov <[email protected]>2026-03-26 11:00:16 +0300
commit9852998440dcaa3eec11377553e996ff9852bb4e (patch)
tree83fd6cf6a491aba90ce28060576fdbf736939227 /library/cpp/yt
parent46c6fa262d8246e71e7f5ed33eb8458f45c5ddf7 (diff)
Add suggestions on enum parse error
commit_hash:3b7f35f613737aa92f473877e8b24782f7dfcd2a
Diffstat (limited to 'library/cpp/yt')
-rw-r--r--library/cpp/yt/string/enum-inl.h26
-rw-r--r--library/cpp/yt/string/enum.cpp40
-rw-r--r--library/cpp/yt/string/enum.h3
-rw-r--r--library/cpp/yt/string/unittests/enum_ut.cpp2
4 files changed, 63 insertions, 8 deletions
diff --git a/library/cpp/yt/string/enum-inl.h b/library/cpp/yt/string/enum-inl.h
index 9f8ca893d2f..14d26c61158 100644
--- a/library/cpp/yt/string/enum-inl.h
+++ b/library/cpp/yt/string/enum-inl.h
@@ -13,16 +13,28 @@
#include <util/string/printf.h>
#include <util/string/strip.h>
+#include <span>
+
namespace NYT {
////////////////////////////////////////////////////////////////////////////////
namespace NDetail {
+////////////////////////////////////////////////////////////////////////////////
+
+using TEnumSuggestionsCalculator = std::string (*)(
+ TStringBuf value,
+ const std::span<const TStringBuf>& domainNames);
+
+extern "C" TEnumSuggestionsCalculator TryGetEnumSuggestionsCalculator();
+
[[noreturn]]
void ThrowMalformedEnumValueException(
TStringBuf typeName,
- TStringBuf value);
+ TStringBuf value,
+ const std::span<const TStringBuf>& domainNames = {});
+
void FormatUnknownEnumValue(
auto* builder,
@@ -32,8 +44,12 @@ void FormatUnknownEnumValue(
builder->AppendFormat("%v::unknown-%v", name, ToUnderlying(value));
}
+////////////////////////////////////////////////////////////////////////////////
+
} // namespace NDetail
+////////////////////////////////////////////////////////////////////////////////
+
template <class T>
std::optional<T> TryParseEnum(TStringBuf str, bool enableUnknown)
{
@@ -80,7 +96,13 @@ T ParseEnum(TStringBuf str)
if (auto optionalResult = TryParseEnum<T>(str, /*enableUnkown*/ true)) {
return *optionalResult;
}
- NYT::NDetail::ThrowMalformedEnumValueException(TEnumTraits<T>::GetTypeName(), str);
+
+ std::span<const TStringBuf> domainNames;
+ if constexpr (requires { TEnumTraits<T>::GetDomainNames(); }) {
+ domainNames = TEnumTraits<T>::GetDomainNames();
+ }
+
+ NYT::NDetail::ThrowMalformedEnumValueException(TEnumTraits<T>::GetTypeName(), str, domainNames);
}
template <class T>
diff --git a/library/cpp/yt/string/enum.cpp b/library/cpp/yt/string/enum.cpp
index 844254faa0f..beeba753daf 100644
--- a/library/cpp/yt/string/enum.cpp
+++ b/library/cpp/yt/string/enum.cpp
@@ -8,11 +8,39 @@ namespace NYT {
namespace NDetail {
-void ThrowMalformedEnumValueException(TStringBuf typeName, TStringBuf value)
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+
+extern "C" TEnumSuggestionsCalculator TryGetEnumSuggestionsCalculatorWeak()
+{
+ return nullptr;
+}
+
+__pragma(comment(linker, "/alternatename:TryGetEnumSuggestionsCalculator=TryGetEnumSuggestionsCalculatorWeak"))
+
+#else
+
+extern "C" Y_WEAK TEnumSuggestionsCalculator TryGetEnumSuggestionsCalculator()
{
- throw TSimpleException(Format("Error parsing %v value %Qv",
- typeName,
- value));
+ return nullptr;
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+void ThrowMalformedEnumValueException(
+ TStringBuf typeName,
+ TStringBuf value,
+ const std::span<const TStringBuf>& domainNames)
+{
+ auto errorMessage = Format("Error parsing %v value %Qv", typeName, value);
+ auto suggestionsCalculator = TryGetEnumSuggestionsCalculator();
+ if (!domainNames.empty() && suggestionsCalculator) {
+ errorMessage += Format("; closest possible values are %v", suggestionsCalculator(value, domainNames));
+ }
+ throw TSimpleException(errorMessage);
}
template <bool ThrowOnError>
@@ -32,8 +60,12 @@ std::optional<std::string> DecodeEnumValueImpl(TStringBuf value)
return camelValue;
}
+////////////////////////////////////////////////////////////////////////////////
+
} // namespace NDetail
+////////////////////////////////////////////////////////////////////////////////
+
std::optional<std::string> TryDecodeEnumValue(TStringBuf value)
{
return NDetail::DecodeEnumValueImpl<false>(value);
diff --git a/library/cpp/yt/string/enum.h b/library/cpp/yt/string/enum.h
index de7d6a52fac..322485a560d 100644
--- a/library/cpp/yt/string/enum.h
+++ b/library/cpp/yt/string/enum.h
@@ -17,6 +17,9 @@ std::string EncodeEnumValue(TStringBuf value);
template <class T>
std::optional<T> TryParseEnum(TStringBuf str, bool enableUnknown = false);
+//! Parses an enum value from a string.
+//! Link against library/cpp/yt/string/enable_enum_suggestions_on_enum_parse_error
+//! to include suggestions in the exception message on parse failure.
template <class T>
T ParseEnum(TStringBuf str);
diff --git a/library/cpp/yt/string/unittests/enum_ut.cpp b/library/cpp/yt/string/unittests/enum_ut.cpp
index 39dbdfd2075..b262568565c 100644
--- a/library/cpp/yt/string/unittests/enum_ut.cpp
+++ b/library/cpp/yt/string/unittests/enum_ut.cpp
@@ -126,5 +126,3 @@ TEST(TParseEnumTest, ParseBitEnum)
} // namespace
} // namespace NYT
-
-