aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-12-26 10:52:40 +0300
committerarkady-e1ppa <arkady-e1ppa@yandex-team.com>2024-12-26 11:12:17 +0300
commit0328aa1f62630f14d06076175e2f3750969ac813 (patch)
treea2652fb95c5a603e15f1692b43b10e4bf036f084
parentb4473180e344fac1deb5f4e85fc681efe2c708de (diff)
downloadydb-0328aa1f62630f14d06076175e2f3750969ac813.tar.gz
YT-21233: Drop dependency on yson in library/cpp/yt/error by switch to std::string everywhere
done commit_hash:8a83afa39917ba66a5161388a7cd74a4488d9908
-rw-r--r--library/cpp/yt/error/error.cpp38
-rw-r--r--library/cpp/yt/error/error.h2
-rw-r--r--library/cpp/yt/error/error_attribute-inl.h33
-rw-r--r--library/cpp/yt/error/error_attribute.h15
-rw-r--r--library/cpp/yt/error/error_attributes-inl.h18
-rw-r--r--library/cpp/yt/error/error_attributes.cpp10
-rw-r--r--library/cpp/yt/error/error_attributes.h4
-rw-r--r--library/cpp/yt/error/origin_attributes.cpp15
-rw-r--r--library/cpp/yt/error/text_yson.cpp436
-rw-r--r--library/cpp/yt/error/text_yson.h104
-rw-r--r--library/cpp/yt/error/ya.make2
-rw-r--r--library/cpp/yt/yson_string/convert.cpp414
-rw-r--r--library/cpp/yt/yson_string/convert.h96
-rw-r--r--yt/yt/core/misc/error-inl.h4
-rw-r--r--yt/yt/core/misc/error.cpp18
-rw-r--r--yt/yt/core/yson/writer.cpp4
-rw-r--r--yt/yt/core/ytree/convert-inl.h4
-rw-r--r--yt/yt/core/ytree/unittests/text_yson_convert_ut.cpp65
18 files changed, 650 insertions, 632 deletions
diff --git a/library/cpp/yt/error/error.cpp b/library/cpp/yt/error/error.cpp
index 59eea6ce8c..866c76eec8 100644
--- a/library/cpp/yt/error/error.cpp
+++ b/library/cpp/yt/error/error.cpp
@@ -18,8 +18,6 @@
namespace NYT {
-using namespace NYson;
-
////////////////////////////////////////////////////////////////////////////////
void FormatValue(TStringBuilderBase* builder, TErrorCode code, TStringBuf spec)
@@ -494,10 +492,8 @@ TError TError::Truncate(
};
auto truncateAttributes = [stringLimit, &attributeWhitelist] (const TErrorAttributes& attributes, TErrorAttributes* mutableAttributes) {
- for (const auto& key : attributes.ListKeys()) {
- const auto& value = attributes.FindValue(key);
-
- if (std::ssize(value.AsStringBuf()) > stringLimit && !attributeWhitelist.contains(key)) {
+ for (const auto& [key, value] : attributes.ListPairs()) {
+ if (std::ssize(value) > stringLimit && !attributeWhitelist.contains(key)) {
mutableAttributes->SetValue(
key,
NYT::ToErrorAttributeValue("...<attribute truncated>..."));
@@ -559,8 +555,8 @@ TError TError::Truncate(
};
auto truncateAttributes = [stringLimit, &attributeWhitelist] (TErrorAttributes* attributes) {
- for (const auto& key : attributes->ListKeys()) {
- if (std::ssize(attributes->FindValue(key).AsStringBuf()) > stringLimit && !attributeWhitelist.contains(key)) {
+ for (const auto& [key, value] : attributes->ListPairs()) {
+ if (std::ssize(value) > stringLimit && !attributeWhitelist.contains(key)) {
attributes->SetValue(
key,
NYT::ToErrorAttributeValue("...<attribute truncated>..."));
@@ -718,15 +714,15 @@ void AppendIndent(TStringBuilderBase* builer, int indent)
builer->AppendChar(' ', indent);
}
-void AppendAttribute(TStringBuilderBase* builder, const TString& key, const TString& value, int indent)
+void AppendAttribute(TStringBuilderBase* builder, const std::string& key, const std::string& value, int indent)
{
AppendIndent(builder, indent + 4);
- if (!value.Contains('\n')) {
+ if (value.find('\n') == std::string::npos) {
builder->AppendFormat("%-15s %s", key, value);
} else {
builder->AppendString(key);
- TString indentedValue = "\n" + value;
- SubstGlobal(indentedValue, "\n", "\n" + TString{static_cast<size_t>(indent + 8), ' '});
+ std::string indentedValue = "\n" + value;
+ SubstGlobal(indentedValue, "\n", "\n" + std::string(static_cast<size_t>(indent + 8), ' '));
// Now first line in indentedValue is empty and every other line is indented by 8 spaces.
builder->AppendString(indentedValue);
}
@@ -735,16 +731,16 @@ void AppendAttribute(TStringBuilderBase* builder, const TString& key, const TStr
void AppendError(TStringBuilderBase* builder, const TError& error, int indent)
{
- auto isStringTextYson = [] (const NYson::TYsonString& str) {
+ auto isStringTextYson = [] (TStringBuf str) {
return
str &&
- std::ssize(str.AsStringBuf()) != 0 &&
- str.AsStringBuf().front() == '\"';
+ std::ssize(str) != 0 &&
+ str.front() == '\"';
};
- auto isBoolTextYson = [] (const NYson::TYsonString& str) {
+ auto isBoolTextYson = [] (TStringBuf str) {
return
- str.AsStringBuf() == "%false" ||
- str.AsStringBuf() == "%true";
+ str == "%false" ||
+ str == "%true";
};
if (error.IsOK()) {
@@ -787,11 +783,11 @@ void AppendError(TStringBuilderBase* builder, const TError& error, int indent)
for (const auto& [key, value] : error.Attributes().ListPairs()) {
if (isStringTextYson(value)) {
- AppendAttribute(builder, key, ConvertFromTextYsonString<TString>(value), indent);
+ AppendAttribute(builder, key, NDetail::ConvertFromTextYsonString<std::string>(value), indent);
} else if (isBoolTextYson(value)) {
- AppendAttribute(builder, key, TString{FormatBool(ConvertFromTextYsonString<bool>(value))}, indent);
+ AppendAttribute(builder, key, std::string(FormatBool(NDetail::ConvertFromTextYsonString<bool>(value))), indent);
} else {
- AppendAttribute(builder, key, value.ToString(), indent);
+ AppendAttribute(builder, key, value, indent);
}
}
diff --git a/library/cpp/yt/error/error.h b/library/cpp/yt/error/error.h
index eed1cfb75d..3def2c4b50 100644
--- a/library/cpp/yt/error/error.h
+++ b/library/cpp/yt/error/error.h
@@ -6,8 +6,6 @@
#include <library/cpp/yt/error/mergeable_dictionary.h>
-#include <library/cpp/yt/yson/public.h>
-
#include <library/cpp/yt/yson_string/convert.h>
#include <library/cpp/yt/yson_string/string.h>
diff --git a/library/cpp/yt/error/error_attribute-inl.h b/library/cpp/yt/error/error_attribute-inl.h
index df7696b85b..412b497128 100644
--- a/library/cpp/yt/error/error_attribute-inl.h
+++ b/library/cpp/yt/error/error_attribute-inl.h
@@ -4,8 +4,7 @@
#include "error_attribute.h"
#endif
-#include <library/cpp/yt/yson_string/convert.h>
-#include <library/cpp/yt/yson_string/format.h>
+#include "text_yson.h"
namespace NYT {
@@ -14,40 +13,22 @@ namespace NYT {
namespace NAttributeValueConversionImpl {
template <CPrimitiveConvertible T>
-NYson::TYsonString TagInvoke(TTagInvokeTag<ToErrorAttributeValue>, const T& value)
+std::string TagInvoke(TTagInvokeTag<ToErrorAttributeValue>, const T& value)
{
if constexpr (std::constructible_from<TStringBuf, const T&>) {
- return NYson::ConvertToTextYsonString(TStringBuf(value));
+ return NDetail::ConvertToTextYsonString(TStringBuf(value));
} else {
- return NYson::ConvertToTextYsonString(value);
+ return NDetail::ConvertToTextYsonString(value);
}
}
////////////////////////////////////////////////////////////////////////////////
-inline bool IsBinaryYson(const NYson::TYsonString& yson)
-{
- using namespace NYson::NDetail;
-
- auto view = yson.AsStringBuf();
- return
- std::ssize(view) != 0 &&
- (view.front() == EntitySymbol ||
- view.front() == StringMarker ||
- view.front() == Int64Marker ||
- view.front() == DoubleMarker ||
- view.front() == FalseMarker ||
- view.front() == TrueMarker ||
- view.front() == Uint64Marker);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
template <CPrimitiveConvertible T>
-T TagInvoke(TFrom<T>, const NYson::TYsonString& value)
+T TagInvoke(TFrom<T>, TStringBuf value)
{
- YT_VERIFY(!IsBinaryYson(value));
- return NYson::ConvertFromTextYsonString<T>(value);
+ YT_VERIFY(!NDetail::IsBinaryYson(value));
+ return NDetail::ConvertFromTextYsonString<T>(value);
}
} // namespace NAttributeValueConversionImpl
diff --git a/library/cpp/yt/error/error_attribute.h b/library/cpp/yt/error/error_attribute.h
index 8b7a79004a..24ebf30ee7 100644
--- a/library/cpp/yt/error/error_attribute.h
+++ b/library/cpp/yt/error/error_attribute.h
@@ -5,8 +5,7 @@
#include <library/cpp/yt/misc/guid.h>
#include <library/cpp/yt/misc/tag_invoke_cpo.h>
-// TODO(arkady-e1ppa): Eliminate.
-#include <library/cpp/yt/yson_string/string.h>
+#include <string>
namespace NYT {
@@ -55,11 +54,11 @@ inline constexpr NAttributeValueConversionImpl::TFrom<U> FromErrorAttributeValue
template <class T>
concept CConvertibleToAttributeValue = requires (const T& value) {
- { NYT::ToErrorAttributeValue(value) } -> std::same_as<NYson::TYsonString>;
+ { NYT::ToErrorAttributeValue(value) } -> std::same_as<std::string>;
};
template <class T>
-concept CConvertibleFromAttributeValue = requires (const NYson::TYsonString& value) {
+concept CConvertibleFromAttributeValue = requires (TStringBuf value) {
{ NYT::FromErrorAttributeValue<T>(value) } -> std::same_as<T>;
};
@@ -67,12 +66,8 @@ concept CConvertibleFromAttributeValue = requires (const NYson::TYsonString& val
struct TErrorAttribute
{
- // TODO(arkady-e1ppa): Switch to std::string is quite possible
- // however it requires patching IAttributeDictionary or
- // switching it to the std::string first for interop reasons.
- // Do that later.
- using TKey = TString;
- using TValue = NYson::TYsonString;
+ using TKey = std::string;
+ using TValue = std::string;
template <CConvertibleToAttributeValue T>
TErrorAttribute(const TKey& key, const T& value)
diff --git a/library/cpp/yt/error/error_attributes-inl.h b/library/cpp/yt/error/error_attributes-inl.h
index e6b39f531e..399c0792d4 100644
--- a/library/cpp/yt/error/error_attributes-inl.h
+++ b/library/cpp/yt/error/error_attributes-inl.h
@@ -12,9 +12,9 @@ template <class T>
requires CConvertibleFromAttributeValue<T>
T TErrorAttributes::Get(TStringBuf key) const
{
- auto yson = GetValue(key);
+ auto value = GetValue(key);
try {
- return NYT::FromErrorAttributeValue<T>(yson);
+ return NYT::FromErrorAttributeValue<T>(value);
} catch (const std::exception& ex) {
ThrowCannotParseAttributeException(key, ex);
}
@@ -29,7 +29,7 @@ typename TOptionalTraits<T>::TOptional TErrorAttributes::Find(TStringBuf key) co
return typename TOptionalTraits<T>::TOptional();
}
try {
- return NYT::FromErrorAttributeValue<T>(value);
+ return NYT::FromErrorAttributeValue<T>(*value);
} catch (const std::exception& ex) {
ThrowCannotParseAttributeException(key, ex);
}
@@ -55,10 +55,10 @@ template <class T>
requires CConvertibleFromAttributeValue<T>
T TErrorAttributes::GetAndRemove(const TKey& key, const T& defaultValue)
{
- auto result = Find<T>(key);
- if (result) {
+ auto value = Find<T>(key);
+ if (value) {
Remove(key);
- return *result;
+ return *value;
} else {
return defaultValue;
}
@@ -68,11 +68,11 @@ template <class T>
requires CConvertibleFromAttributeValue<T>
typename TOptionalTraits<T>::TOptional TErrorAttributes::FindAndRemove(const TKey& key)
{
- auto result = Find<T>(key);
- if (result) {
+ auto value = Find<T>(key);
+ if (value) {
Remove(key);
}
- return result;
+ return value;
}
template <CMergeableDictionary TDictionary>
diff --git a/library/cpp/yt/error/error_attributes.cpp b/library/cpp/yt/error/error_attributes.cpp
index 06db3b211e..fcfe80c414 100644
--- a/library/cpp/yt/error/error_attributes.cpp
+++ b/library/cpp/yt/error/error_attributes.cpp
@@ -9,7 +9,7 @@ namespace NYT {
std::vector<TErrorAttributes::TKey> TErrorAttributes::ListKeys() const
{
- std::vector<TString> keys;
+ std::vector<TKey> keys;
keys.reserve(Map_.size());
for (const auto& [key, value] : Map_) {
keys.push_back(key);
@@ -27,10 +27,12 @@ std::vector<TErrorAttributes::TKeyValuePair> TErrorAttributes::ListPairs() const
return pairs;
}
-TErrorAttributes::TValue TErrorAttributes::FindValue(TStringBuf key) const
+std::optional<TErrorAttribute::TValue> TErrorAttributes::FindValue(TStringBuf key) const
{
auto it = Map_.find(key);
- return it == Map_.end() ? TValue{} : it->second;
+ return it == Map_.end()
+ ? std::nullopt
+ : std::optional(it->second);
}
void TErrorAttributes::SetValue(const TKey& key, const TValue& value)
@@ -54,7 +56,7 @@ TErrorAttributes::TValue TErrorAttributes::GetValue(TStringBuf key) const
if (!result) {
ThrowNoSuchAttributeException(key);
}
- return result;
+ return *result;
}
void TErrorAttributes::Clear()
diff --git a/library/cpp/yt/error/error_attributes.h b/library/cpp/yt/error/error_attributes.h
index da71af63cc..8ab6388ef3 100644
--- a/library/cpp/yt/error/error_attributes.h
+++ b/library/cpp/yt/error/error_attributes.h
@@ -74,7 +74,7 @@ public:
void MergeFrom(const TDictionary& dict);
private:
- THashMap<TKey, TValue> Map_;
+ THashMap<TKey, TValue, THash<TStringBuf>, TEqualTo<TStringBuf>> Map_;
friend class TErrorOr<void>;
TErrorAttributes() = default;
@@ -86,7 +86,7 @@ private:
TErrorAttributes& operator= (TErrorAttributes&& other) = default;
//! Returns the value of the attribute (null indicates that the attribute is not found).
- TValue FindValue(TStringBuf key) const;
+ std::optional<TValue> FindValue(TStringBuf key) const;
//! Returns the value of the attribute (throws an exception if the attribute is not found).
TValue GetValue(TStringBuf key) const;
diff --git a/library/cpp/yt/error/origin_attributes.cpp b/library/cpp/yt/error/origin_attributes.cpp
index 6f86e31ae8..2abb060ce2 100644
--- a/library/cpp/yt/error/origin_attributes.cpp
+++ b/library/cpp/yt/error/origin_attributes.cpp
@@ -128,22 +128,21 @@ TOriginAttributes ExtractFromDictionaryDefault(TErrorAttributes* attributes)
return result;
}
- // TODO(arkady-e1ppa): Try using std::string here.
- static const TString HostKey("host");
- result.HostHolder = TSharedRef::FromString(attributes->GetAndRemove(HostKey, TString()));
+ static const std::string HostKey("host");
+ result.HostHolder = TSharedRef::FromString(attributes->GetAndRemove(HostKey, std::string()));
result.Host = result.HostHolder.empty() ? TStringBuf() : TStringBuf(result.HostHolder.Begin(), result.HostHolder.End());
- static const TString DatetimeKey("datetime");
+ static const std::string DatetimeKey("datetime");
result.Datetime = attributes->GetAndRemove(DatetimeKey, TInstant());
- static const TString PidKey("pid");
+ static const std::string PidKey("pid");
result.Pid = attributes->GetAndRemove(PidKey, TProcessId{});
- static const TString TidKey("tid");
+ static const std::string TidKey("tid");
result.Tid = attributes->GetAndRemove(TidKey, NThreading::InvalidThreadId);
- static const TString ThreadNameKey("thread");
- result.ThreadName = attributes->GetAndRemove<TString>(ThreadNameKey, TString());
+ static const std::string ThreadNameKey("thread");
+ result.ThreadName = TString(attributes->GetAndRemove(ThreadNameKey, std::string()));
return result;
}
diff --git a/library/cpp/yt/error/text_yson.cpp b/library/cpp/yt/error/text_yson.cpp
new file mode 100644
index 0000000000..42ad52bbcc
--- /dev/null
+++ b/library/cpp/yt/error/text_yson.cpp
@@ -0,0 +1,436 @@
+#include "text_yson.h"
+
+#include "error.h"
+
+#include <library/cpp/yt/assert/assert.h>
+
+#include <library/cpp/yt/string/format.h>
+
+#include <library/cpp/yt/coding/varint.h>
+
+#include <library/cpp/yt/misc/cast.h>
+
+#include <array>
+
+#include <util/string/escape.h>
+
+#include <util/stream/mem.h>
+
+namespace NYT::NDetail {
+
+////////////////////////////////////////////////////////////////////////////////
+
+size_t FloatToStringWithNanInf(double value, char* buf, size_t size)
+{
+ if (std::isfinite(value)) {
+ return FloatToString(value, buf, size);
+ }
+
+ static const TStringBuf nanLiteral = "%nan";
+ static const TStringBuf infLiteral = "%inf";
+ static const TStringBuf negativeInfLiteral = "%-inf";
+
+ TStringBuf str;
+ if (std::isnan(value)) {
+ str = nanLiteral;
+ } else if (std::isinf(value) && value > 0) {
+ str = infLiteral;
+ } else {
+ str = negativeInfLiteral;
+ }
+ YT_VERIFY(str.size() + 1 <= size);
+ ::memcpy(buf, str.data(), str.size() + 1);
+ return str.size();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// NB(arkady-e1ppa): Copied from library/cpp/yt/yson_string/format.h
+// to avoid direct dependency on it.
+
+//! Indicates an entity.
+constexpr char EntitySymbol = '#';
+//! Marks the beginning of a binary string literal.
+constexpr char StringMarker = '\x01';
+//! Marks the beginning of a binary i64 literal.
+constexpr char Int64Marker = '\x02';
+//! Marks the beginning of a binary double literal.
+constexpr char DoubleMarker = '\x03';
+//! Marks |false| boolean value.
+constexpr char FalseMarker = '\x04';
+//! Marks |true| boolean value.
+constexpr char TrueMarker = '\x05';
+//! Marks the beginning of a binary ui64 literal.
+constexpr char Uint64Marker = '\x06';
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool IsBinaryYson(TStringBuf str)
+{
+ return
+ std::ssize(str) != 0 &&
+ (str.front() == EntitySymbol ||
+ str.front() == StringMarker ||
+ str.front() == Int64Marker ||
+ str.front() == DoubleMarker ||
+ str.front() == FalseMarker ||
+ str.front() == TrueMarker ||
+ str.front() == Uint64Marker);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <>
+std::string ConvertToTextYsonString<i8>(const i8& value)
+{
+ return ConvertToTextYsonString(static_cast<i64>(value));
+}
+
+template <>
+std::string ConvertToTextYsonString<i32>(const i32& value)
+{
+ return ConvertToTextYsonString(static_cast<i64>(value));
+}
+
+template <>
+std::string ConvertToTextYsonString<i64>(const i64& value)
+{
+ return std::string{::ToString(value)};
+}
+
+template <>
+std::string ConvertToTextYsonString<ui8>(const ui8& value)
+{
+ return ConvertToTextYsonString(static_cast<ui64>(value));
+}
+
+template <>
+std::string ConvertToTextYsonString<ui32>(const ui32& value)
+{
+ return ConvertToTextYsonString(static_cast<ui64>(value));
+}
+
+template <>
+std::string ConvertToTextYsonString<ui64>(const ui64& value)
+{
+ return std::string{::ToString(value) + 'u'};
+}
+
+template <>
+std::string ConvertToTextYsonString<TStringBuf>(const TStringBuf& value)
+{
+ return std::string(NYT::Format("\"%v\"", ::EscapeC(value)));
+}
+
+template <>
+std::string ConvertToTextYsonString<float>(const float& value)
+{
+ return ConvertToTextYsonString(static_cast<double>(value));
+}
+
+template <>
+std::string ConvertToTextYsonString<double>(const double& value)
+{
+ char buf[256];
+ auto str = TStringBuf(buf, NDetail::FloatToStringWithNanInf(value, buf, sizeof(buf)));
+ auto ret = NYT::Format(
+ "%v%v",
+ str,
+ MakeFormatterWrapper([&] (TStringBuilderBase* builder) {
+ if (str.find('.') == TString::npos && str.find('e') == TString::npos && std::isfinite(value)) {
+ builder->AppendChar('.');
+ }
+ }));
+ return std::string(std::move(ret));
+}
+
+template <>
+std::string ConvertToTextYsonString<bool>(const bool& value)
+{
+ return value
+ ? std::string(TStringBuf("%true"))
+ : std::string(TStringBuf("%false"));
+}
+
+template <>
+std::string ConvertToTextYsonString<TInstant>(const TInstant& value)
+{
+ return ConvertToTextYsonString(TStringBuf(value.ToString()));
+}
+
+template <>
+std::string ConvertToTextYsonString<TDuration>(const TDuration& value)
+{
+ // ConvertTo does unchecked cast to i64 :(.
+ return ConvertToTextYsonString(static_cast<i64>(value.MilliSeconds()));
+}
+
+template <>
+std::string ConvertToTextYsonString<TGuid>(const TGuid& value)
+{
+ return ConvertToTextYsonString(TStringBuf(NYT::ToString(value)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+namespace {
+
+template <class TSomeInt>
+TSomeInt ReadTextUint(TStringBuf strBuf)
+{
+ // Drop 'u'
+ return ::FromString<TSomeInt>(TStringBuf{strBuf.data(), strBuf.length() - 1});
+}
+
+template <class TSomeInt>
+TSomeInt ReadTextInt(TStringBuf strBuf)
+{
+ return ::FromString<TSomeInt>(TStringBuf{strBuf.data(), strBuf.length()});
+}
+
+bool IsNumeric(TStringBuf strBuf)
+{
+ bool isNumeric = true;
+ bool isNegative = false;
+ for (int i = 0; i < std::ssize(strBuf); ++i) {
+ char c = strBuf[i];
+
+ if (!('0' <= c && c <= '9')) {
+ if (i == 0 && c == '-') {
+ isNegative = true;
+ continue;
+ }
+ if (i == std::ssize(strBuf) - 1 && c == 'u' && !isNegative) {
+ continue;
+ }
+ isNumeric = false;
+ break;
+ }
+ }
+
+ return isNumeric;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class TSomeInt>
+TSomeInt ParseSomeIntFromTextYsonString(TStringBuf strBuf)
+{
+ if (std::ssize(strBuf) == 0 || !IsNumeric(strBuf)) {
+ THROW_ERROR_EXCEPTION(
+ "Unexpected %v\n"
+ "Value is not numeric",
+ strBuf);
+ }
+
+ if (strBuf.back() == 'u') {
+ // Drop 'u'
+ return ReadTextUint<TSomeInt>(strBuf);
+ } else {
+ return ReadTextInt<TSomeInt>(strBuf);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+TString DoParseStringFromTextYson(TStringBuf strBuf)
+{
+ // Remove quotation marks.
+ return ::UnescapeC(TStringBuf{strBuf.data() + 1, strBuf.length() - 2});
+}
+
+TString ParseStringFromTextYsonString(TStringBuf strBuf)
+{
+ if (std::ssize(strBuf) < 2 || strBuf.front() != '\"' || strBuf.back() != '\"') {
+ THROW_ERROR_EXCEPTION(
+ "Unexpected %v\n"
+ "Text yson string must begin and end with \\\"",
+ strBuf);
+ }
+ return DoParseStringFromTextYson(strBuf);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+double ParseDoubleFromTextYsonString(TStringBuf strBuf)
+{
+ if (std::ssize(strBuf) < 2) {
+ THROW_ERROR_EXCEPTION(
+ "Incorrect remaining string length: expected at least 2, got %v",
+ std::ssize(strBuf));
+ }
+
+ // Check special values first.
+ // %nan
+ // %inf, %+inf, %-inf
+ if (strBuf[0] == '%') {
+ switch (strBuf[1]) {
+ case '+':
+ case 'i':
+ return std::numeric_limits<double>::infinity();
+
+ case '-':
+ return -std::numeric_limits<double>::infinity();
+
+ case 'n':
+ return std::numeric_limits<double>::quiet_NaN();
+
+ default:
+ THROW_ERROR_EXCEPTION(
+ "Incorrect %%-literal %v",
+ strBuf);
+ }
+ }
+
+ return ::FromString<double>(strBuf);
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define PARSE_INT(type, underlyingType) \
+ template <> \
+ type ConvertFromTextYsonString<type>(TStringBuf str) \
+ { \
+ try { \
+ return CheckedIntegralCast<type>(ParseSomeIntFromTextYsonString<underlyingType>(str)); \
+ } catch (const std::exception& ex) { \
+ THROW_ERROR_EXCEPTION("Error parsing \"" #type "\" value from YSON") << ex; \
+ } \
+ }
+
+PARSE_INT(i8, i64)
+PARSE_INT(i16, i64)
+PARSE_INT(i32, i64)
+PARSE_INT(i64, i64)
+PARSE_INT(ui8, ui64)
+PARSE_INT(ui16, ui64)
+PARSE_INT(ui32, ui64)
+PARSE_INT(ui64, ui64)
+
+#undef PARSE
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <>
+TString ConvertFromTextYsonString<TString>(TStringBuf str)
+{
+ try {
+ return ParseStringFromTextYsonString(str);
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"string\" value from YSON") << ex;
+ }
+}
+
+template <>
+std::string ConvertFromTextYsonString<std::string>(TStringBuf str)
+{
+ return std::string(ConvertFromTextYsonString<TString>(str));
+}
+
+template <>
+float ConvertFromTextYsonString<float>(TStringBuf str)
+{
+ try {
+ return static_cast<float>(ParseDoubleFromTextYsonString(str));
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"float\" value from YSON") << ex;
+ }
+}
+
+template <>
+double ConvertFromTextYsonString<double>(TStringBuf str)
+{
+ try {
+ return ParseDoubleFromTextYsonString(str);
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"double\" value from YSON") << ex;
+ }
+}
+
+template <>
+bool ConvertFromTextYsonString<bool>(TStringBuf strBuf)
+{
+ try {
+ if (std::ssize(strBuf) == 0) {
+ THROW_ERROR_EXCEPTION("Empty string");
+ }
+
+ char ch = strBuf.front();
+
+ if (ch == '%') {
+ if (strBuf != "%true" && strBuf != "%false") {
+ THROW_ERROR_EXCEPTION(
+ "Expected %%true or %%false but found %v",
+ strBuf);
+ }
+ return strBuf == "%true";
+ }
+
+ if (ch == '\"') {
+ return ParseBool(DoParseStringFromTextYson(strBuf));
+ }
+
+ // NB(arkady-e1ppa): This check is linear in size(strBuf)
+ // And thus is tried as the last resort.
+ if (IsNumeric(strBuf)) {
+ auto checkValue = [&] (const auto& functor) {
+ auto value = functor(strBuf);
+ if (value != 0 && value != 1) {
+ THROW_ERROR_EXCEPTION(
+ "Expected 0 or 1 but found %v",
+ value);
+ }
+ return static_cast<bool>(value);
+ };
+
+ if (strBuf.back() == 'u') {
+ return checkValue(&ReadTextUint<ui64>);
+ } else {
+ return checkValue(&ReadTextInt<i64>);
+ }
+ }
+
+ THROW_ERROR_EXCEPTION(
+ "Unexpected %v\n"
+ "No known conversion to \"boolean\" value",
+ strBuf);
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"boolean\" value from YSON") << ex;
+ }
+}
+
+template <>
+TInstant ConvertFromTextYsonString<TInstant>(TStringBuf str)
+{
+ try {
+ return TInstant::ParseIso8601(ParseStringFromTextYsonString(str));
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"instant\" value from YSON") << ex;
+ }
+}
+
+template <>
+TDuration ConvertFromTextYsonString<TDuration>(TStringBuf str)
+{
+ try {
+ return TDuration::MilliSeconds(ParseSomeIntFromTextYsonString<i64>(str));
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"duration\" value from YSON") << ex;
+ }
+}
+
+template <>
+TGuid ConvertFromTextYsonString<TGuid>(TStringBuf str)
+{
+ try {
+ return TGuid::FromString(ParseStringFromTextYsonString(str));
+ } catch (const std::exception& ex) {
+ THROW_ERROR_EXCEPTION("Error parsing \"guid\" value from YSON") << ex;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NDetail
diff --git a/library/cpp/yt/error/text_yson.h b/library/cpp/yt/error/text_yson.h
new file mode 100644
index 0000000000..efd3d562bf
--- /dev/null
+++ b/library/cpp/yt/error/text_yson.h
@@ -0,0 +1,104 @@
+#pragma once
+
+#include <library/cpp/yt/misc/guid.h>
+
+#include <util/datetime/base.h>
+
+#include <util/generic/strbuf.h>
+
+#include <string>
+
+namespace NYT::NDetail {
+
+////////////////////////////////////////////////////////////////////////////////
+
+size_t FloatToStringWithNanInf(double value, char* buf, size_t size);
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool IsBinaryYson(TStringBuf str);
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+std::string ConvertToTextYsonString(const T& value) = delete;
+template <class T>
+T ConvertFromTextYsonString(TStringBuf str) = delete;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <>
+std::string ConvertToTextYsonString<i8>(const i8& value);
+template <>
+std::string ConvertToTextYsonString<i32>(const i32& value);
+template <>
+std::string ConvertToTextYsonString<i64>(const i64& value);
+
+template <>
+std::string ConvertToTextYsonString<ui8>(const ui8& value);
+template <>
+std::string ConvertToTextYsonString<ui32>(const ui32& value);
+template <>
+std::string ConvertToTextYsonString<ui64>(const ui64& value);
+
+template <>
+std::string ConvertToTextYsonString<TStringBuf>(const TStringBuf& value);
+
+template <>
+std::string ConvertToTextYsonString<float>(const float& value);
+template <>
+std::string ConvertToTextYsonString<double>(const double& value);
+
+template <>
+std::string ConvertToTextYsonString<bool>(const bool& value);
+
+template <>
+std::string ConvertToTextYsonString<TInstant>(const TInstant& value);
+
+template <>
+std::string ConvertToTextYsonString<TDuration>(const TDuration& value);
+
+template <>
+std::string ConvertToTextYsonString<TGuid>(const TGuid& value);
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <>
+i8 ConvertFromTextYsonString<i8>(TStringBuf str);
+template <>
+i32 ConvertFromTextYsonString<i32>(TStringBuf str);
+template <>
+i64 ConvertFromTextYsonString<i64>(TStringBuf str);
+
+template <>
+ui8 ConvertFromTextYsonString<ui8>(TStringBuf str);
+template <>
+ui32 ConvertFromTextYsonString<ui32>(TStringBuf str);
+template <>
+ui64 ConvertFromTextYsonString<ui64>(TStringBuf str);
+
+template <>
+TString ConvertFromTextYsonString<TString>(TStringBuf str);
+template <>
+std::string ConvertFromTextYsonString<std::string>(TStringBuf str);
+
+template <>
+float ConvertFromTextYsonString<float>(TStringBuf str);
+template <>
+double ConvertFromTextYsonString<double>(TStringBuf str);
+
+template <>
+bool ConvertFromTextYsonString<bool>(TStringBuf str);
+
+template <>
+TInstant ConvertFromTextYsonString<TInstant>(TStringBuf str);
+
+template <>
+TDuration ConvertFromTextYsonString<TDuration>(TStringBuf str);
+
+template <>
+TGuid ConvertFromTextYsonString<TGuid>(TStringBuf str);
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NDetail
diff --git a/library/cpp/yt/error/ya.make b/library/cpp/yt/error/ya.make
index ca4370ef9d..b6dcc07343 100644
--- a/library/cpp/yt/error/ya.make
+++ b/library/cpp/yt/error/ya.make
@@ -9,7 +9,6 @@ PEERDIR(
library/cpp/yt/misc
library/cpp/yt/threading
library/cpp/yt/string
- library/cpp/yt/yson_string # TODO(arkady-e1ppa): eliminate
library/cpp/yt/logging # TODO(arkady-e1ppa): Consider logging error_code crashes to stderr and drop this dep.
util
@@ -20,6 +19,7 @@ SRCS(
error_attributes.cpp
error_code.cpp
origin_attributes.cpp
+ text_yson.cpp
)
END()
diff --git a/library/cpp/yt/yson_string/convert.cpp b/library/cpp/yt/yson_string/convert.cpp
index 1beb7cc4c7..ca34428290 100644
--- a/library/cpp/yt/yson_string/convert.cpp
+++ b/library/cpp/yt/yson_string/convert.cpp
@@ -19,35 +19,6 @@ namespace NYT::NYson {
////////////////////////////////////////////////////////////////////////////////
-namespace NDetail {
-
-size_t FloatToStringWithNanInf(double value, char* buf, size_t size)
-{
- if (std::isfinite(value)) {
- return FloatToString(value, buf, size);
- }
-
- static const TStringBuf nanLiteral = "%nan";
- static const TStringBuf infLiteral = "%inf";
- static const TStringBuf negativeInfLiteral = "%-inf";
-
- TStringBuf str;
- if (std::isnan(value)) {
- str = nanLiteral;
- } else if (std::isinf(value) && value > 0) {
- str = infLiteral;
- } else {
- str = negativeInfLiteral;
- }
- YT_VERIFY(str.size() + 1 <= size);
- ::memcpy(buf, str.data(), str.size() + 1);
- return str.size();
-}
-
-} // namespace NDetail
-
-////////////////////////////////////////////////////////////////////////////////
-
template <>
TYsonString ConvertToYsonString<i8>(const i8& value)
{
@@ -416,389 +387,4 @@ TGuid ConvertFromYsonString<TGuid>(const TYsonStringBuf& str)
////////////////////////////////////////////////////////////////////////////////
-template <>
-TYsonString ConvertToTextYsonString<i8>(const i8& value)
-{
- return ConvertToTextYsonString(static_cast<i64>(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<i32>(const i32& value)
-{
- return ConvertToTextYsonString(static_cast<i64>(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<i64>(const i64& value)
-{
- return TYsonString{::ToString(value)};
-}
-
-template <>
-TYsonString ConvertToTextYsonString<ui8>(const ui8& value)
-{
- return ConvertToTextYsonString(static_cast<ui64>(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<ui32>(const ui32& value)
-{
- return ConvertToTextYsonString(static_cast<ui64>(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<ui64>(const ui64& value)
-{
- return TYsonString{::ToString(value) + 'u'};
-}
-
-template <>
-TYsonString ConvertToTextYsonString<TString>(const TString& value)
-{
- return ConvertToTextYsonString(TStringBuf(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<std::string>(const std::string& value)
-{
- return ConvertToTextYsonString(TStringBuf(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<TStringBuf>(const TStringBuf& value)
-{
- return TYsonString(NYT::Format("\"%v\"", ::EscapeC(value)));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<std::string_view>(const std::string_view& value)
-{
- return ConvertToTextYsonString(TStringBuf(value));
-}
-
-TYsonString ConvertToTextYsonString(const char* value)
-{
- return ConvertToTextYsonString(TStringBuf(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<float>(const float& value)
-{
- return ConvertToTextYsonString(static_cast<double>(value));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<double>(const double& value)
-{
- char buf[256];
- auto str = TStringBuf(buf, NDetail::FloatToStringWithNanInf(value, buf, sizeof(buf)));
- auto ret = NYT::Format(
- "%v%v",
- str,
- MakeFormatterWrapper([&] (TStringBuilderBase* builder) {
- if (str.find('.') == TString::npos && str.find('e') == TString::npos && std::isfinite(value)) {
- builder->AppendChar('.');
- }
- }));
- return TYsonString(std::move(ret));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<bool>(const bool& value)
-{
- return value
- ? TYsonString(TStringBuf("%true"))
- : TYsonString(TStringBuf("%false"));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<TInstant>(const TInstant& value)
-{
- return ConvertToTextYsonString(value.ToString());
-}
-
-template <>
-TYsonString ConvertToTextYsonString<TDuration>(const TDuration& value)
-{
- // ConvertTo does unchecked cast to i64 :(.
- return ConvertToTextYsonString(static_cast<i64>(value.MilliSeconds()));
-}
-
-template <>
-TYsonString ConvertToTextYsonString<TGuid>(const TGuid& value)
-{
- return ConvertToTextYsonString(NYT::ToString(value));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-namespace {
-
-template <class TSomeInt>
-TSomeInt ReadTextUint(TStringBuf strBuf)
-{
- // Drop 'u'
- return ::FromString<TSomeInt>(TStringBuf{strBuf.data(), strBuf.length() - 1});
-}
-
-template <class TSomeInt>
-TSomeInt ReadTextInt(TStringBuf strBuf)
-{
- return ::FromString<TSomeInt>(TStringBuf{strBuf.data(), strBuf.length()});
-}
-
-bool IsNumeric(TStringBuf strBuf)
-{
- bool isNumeric = true;
- bool isNegative = false;
- for (int i = 0; i < std::ssize(strBuf); ++i) {
- char c = strBuf[i];
-
- if (!('0' <= c && c <= '9')) {
- if (i == 0 && c == '-') {
- isNegative = true;
- continue;
- }
- if (i == std::ssize(strBuf) - 1 && c == 'u' && !isNegative) {
- continue;
- }
- isNumeric = false;
- break;
- }
- }
-
- return isNumeric;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <class TSomeInt>
-TSomeInt ParseSomeIntFromTextYsonString(const TYsonStringBuf& str)
-{
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
-
- if (std::ssize(strBuf) == 0 || !IsNumeric(strBuf)) {
- throw TYsonLiteralParseException(NYT::Format(
- "Unexpected %v\n"
- "Value is not numeric",
- strBuf));
- }
-
- if (strBuf.back() == 'u') {
- // Drop 'u'
- return ReadTextUint<TSomeInt>(strBuf);
- } else {
- return ReadTextInt<TSomeInt>(strBuf);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-TString DoParseStringFromTextYson(TStringBuf strBuf)
-{
- // Remove quotation marks.
- return ::UnescapeC(TStringBuf{strBuf.data() + 1, strBuf.length() - 2});
-}
-
-TString ParseStringFromTextYsonString(const TYsonStringBuf& str)
-{
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
- if (std::ssize(strBuf) < 2 || strBuf.front() != '\"' || strBuf.back() != '\"') {
- throw TYsonLiteralParseException(Format(
- "Unexpected %v\n"
- "Text yson string must begin and end with \\\"",
- strBuf));
- }
- return DoParseStringFromTextYson(strBuf);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-double ParseDoubleFromTextYsonString(const TYsonStringBuf& str)
-{
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
-
- if (std::ssize(strBuf) < 2) {
- throw TYsonLiteralParseException(Format(
- "Incorrect remaining string length: expected at least 2, got %v",
- std::ssize(strBuf)));
- }
-
- // Check special values first.
- // %nan
- // %inf, %+inf, %-inf
- if (strBuf[0] == '%') {
- switch (strBuf[1]) {
- case '+':
- case 'i':
- return std::numeric_limits<double>::infinity();
-
- case '-':
- return -std::numeric_limits<double>::infinity();
-
- case 'n':
- return std::numeric_limits<double>::quiet_NaN();
-
- default:
- throw TYsonLiteralParseException(Format(
- "Incorrect %%-literal %v",
- strBuf));
- }
- }
-
- return ::FromString<double>(strBuf);
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-
-#define PARSE_INT(type, underlyingType) \
- template <> \
- type ConvertFromTextYsonString<type>(const TYsonStringBuf& str) \
- { \
- try { \
- return CheckedIntegralCast<type>(ParseSomeIntFromTextYsonString<underlyingType>(str)); \
- } catch (const std::exception& ex) { \
- throw TYsonLiteralParseException(ex, "Error parsing \"" #type "\" value from YSON"); \
- } \
- }
-
-PARSE_INT(i8, i64)
-PARSE_INT(i16, i64)
-PARSE_INT(i32, i64)
-PARSE_INT(i64, i64)
-PARSE_INT(ui8, ui64)
-PARSE_INT(ui16, ui64)
-PARSE_INT(ui32, ui64)
-PARSE_INT(ui64, ui64)
-
-#undef PARSE
-
-template <>
-TString ConvertFromTextYsonString<TString>(const TYsonStringBuf& str)
-{
- try {
- return ParseStringFromTextYsonString(str);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"string\" value from YSON");
- }
-}
-
-template <>
-std::string ConvertFromTextYsonString<std::string>(const TYsonStringBuf& str)
-{
- return std::string{ConvertFromTextYsonString<TString>(str)};
-}
-
-template <>
-float ConvertFromTextYsonString<float>(const TYsonStringBuf& str)
-{
- try {
- return static_cast<float>(ParseDoubleFromTextYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"float\" value from YSON");
- }
-}
-
-template <>
-double ConvertFromTextYsonString<double>(const TYsonStringBuf& str)
-{
- try {
- return ParseDoubleFromTextYsonString(str);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"double\" value from YSON");
- }
-}
-
-template <>
-bool ConvertFromTextYsonString<bool>(const TYsonStringBuf& str)
-{
- try {
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
-
- if (std::ssize(strBuf) == 0) {
- throw TYsonLiteralParseException("Empty string");
- }
-
- char ch = strBuf.front();
-
- if (ch == '%') {
- if (strBuf != "%true" && strBuf != "%false") {
- throw TYsonLiteralParseException(Format(
- "Expected %%true or %%false but found %v",
- strBuf));
- }
- return strBuf == "%true";
- }
-
- if (ch == '\"') {
- return ParseBool(DoParseStringFromTextYson(strBuf));
- }
-
- // NB(arkady-e1ppa): This check is linear in size(strBuf)
- // And thus is tried as the last resort.
- if (IsNumeric(strBuf)) {
- auto checkValue = [&] (const auto& functor) {
- auto value = functor(strBuf);
- if (value != 0 && value != 1) {
- throw TYsonLiteralParseException(Format(
- "Expected 0 or 1 but found %v",
- value));
- }
- return static_cast<bool>(value);
- };
-
- if (strBuf.back() == 'u') {
- return checkValue(&ReadTextUint<ui64>);
- } else {
- return checkValue(&ReadTextInt<i64>);
- }
- }
-
- throw TYsonLiteralParseException(Format(
- "Unexpected %v\n"
- "No known conversion to \"boolean\" value",
- strBuf));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"boolean\" value from YSON");
- }
-}
-
-template <>
-TInstant ConvertFromTextYsonString<TInstant>(const TYsonStringBuf& str)
-{
- try {
- return TInstant::ParseIso8601(ParseStringFromTextYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"instant\" value from YSON");
- }
-}
-
-template <>
-TDuration ConvertFromTextYsonString<TDuration>(const TYsonStringBuf& str)
-{
- try {
- return TDuration::MilliSeconds(ParseSomeIntFromTextYsonString<i64>(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"duration\" value from YSON");
- }
-}
-
-template <>
-TGuid ConvertFromTextYsonString<TGuid>(const TYsonStringBuf& str)
-{
- try {
- return TGuid::FromString(ParseStringFromTextYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"guid\" value from YSON");
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
} // namespace NYT::NYson
diff --git a/library/cpp/yt/yson_string/convert.h b/library/cpp/yt/yson_string/convert.h
index a51821fa30..3a46eb15a3 100644
--- a/library/cpp/yt/yson_string/convert.h
+++ b/library/cpp/yt/yson_string/convert.h
@@ -14,14 +14,6 @@ namespace NYT::NYson {
////////////////////////////////////////////////////////////////////////////////
-namespace NDetail {
-
-size_t FloatToStringWithNanInf(double value, char* buf, size_t size);
-
-} // namespace NDetail
-
-////////////////////////////////////////////////////////////////////////////////
-
// Generic forward declarations.
template <class T>
@@ -33,13 +25,6 @@ TYsonString ConvertToYsonString(const T& value, EYsonFormat format);
template <class T>
T ConvertFromYsonString(const TYsonStringBuf& str);
-// TODO(arkady-e1ppa): Move those to library/cpp/yt/error
-// and swap to std::string(_view) to drop dep on library/cpp/yson_string.
-template <class T>
-TYsonString ConvertToTextYsonString(const T& value) = delete;
-template <class T>
-T ConvertFromTextYsonString(const TYsonStringBuf& str) = delete;
-
////////////////////////////////////////////////////////////////////////////////
// Basic specializations for ConvertToYsonString.
@@ -129,85 +114,4 @@ TGuid ConvertFromYsonString<TGuid>(const TYsonStringBuf& str);
////////////////////////////////////////////////////////////////////////////////
-template <>
-TYsonString ConvertToTextYsonString<i8>(const i8& value);
-template <>
-TYsonString ConvertToTextYsonString<i32>(const i32& value);
-template <>
-TYsonString ConvertToTextYsonString<i64>(const i64& value);
-
-template <>
-TYsonString ConvertToTextYsonString<ui8>(const ui8& value);
-template <>
-TYsonString ConvertToTextYsonString<ui32>(const ui32& value);
-template <>
-TYsonString ConvertToTextYsonString<ui64>(const ui64& value);
-
-template <>
-TYsonString ConvertToTextYsonString<TString>(const TString& value);
-template <>
-TYsonString ConvertToTextYsonString<std::string>(const std::string& value);
-template <>
-TYsonString ConvertToTextYsonString<TStringBuf>(const TStringBuf& value);
-template <>
-TYsonString ConvertToTextYsonString<std::string_view>(const std::string_view& value);
-TYsonString ConvertToTextYsonString(const char* value);
-
-template <>
-TYsonString ConvertToTextYsonString<float>(const float& value);
-template <>
-TYsonString ConvertToTextYsonString<double>(const double& value);
-
-template <>
-TYsonString ConvertToTextYsonString<bool>(const bool& value);
-
-template <>
-TYsonString ConvertToTextYsonString<TInstant>(const TInstant& value);
-
-template <>
-TYsonString ConvertToTextYsonString<TDuration>(const TDuration& value);
-
-template <>
-TYsonString ConvertToTextYsonString<TGuid>(const TGuid& value);
-
-////////////////////////////////////////////////////////////////////////////////
-
-template <>
-i8 ConvertFromTextYsonString<i8>(const TYsonStringBuf& str);
-template <>
-i32 ConvertFromTextYsonString<i32>(const TYsonStringBuf& str);
-template <>
-i64 ConvertFromTextYsonString<i64>(const TYsonStringBuf& str);
-
-template <>
-ui8 ConvertFromTextYsonString<ui8>(const TYsonStringBuf& str);
-template <>
-ui32 ConvertFromTextYsonString<ui32>(const TYsonStringBuf& str);
-template <>
-ui64 ConvertFromTextYsonString<ui64>(const TYsonStringBuf& str);
-
-template <>
-TString ConvertFromTextYsonString<TString>(const TYsonStringBuf& str);
-template <>
-std::string ConvertFromTextYsonString<std::string>(const TYsonStringBuf& str);
-
-template <>
-float ConvertFromTextYsonString<float>(const TYsonStringBuf& str);
-template <>
-double ConvertFromTextYsonString<double>(const TYsonStringBuf& str);
-
-template <>
-bool ConvertFromTextYsonString<bool>(const TYsonStringBuf& str);
-
-template <>
-TInstant ConvertFromTextYsonString<TInstant>(const TYsonStringBuf& str);
-
-template <>
-TDuration ConvertFromTextYsonString<TDuration>(const TYsonStringBuf& str);
-
-template <>
-TGuid ConvertFromTextYsonString<TGuid>(const TYsonStringBuf& str);
-
-////////////////////////////////////////////////////////////////////////////////
-
} // namespace NYT::NYson
diff --git a/yt/yt/core/misc/error-inl.h b/yt/yt/core/misc/error-inl.h
index f215fcd907..9359cd72f7 100644
--- a/yt/yt/core/misc/error-inl.h
+++ b/yt/yt/core/misc/error-inl.h
@@ -10,9 +10,9 @@ namespace NYT::NAttributeValueConversionImpl {
template <class T>
requires (!CPrimitiveConvertible<T>)
-NYson::TYsonString TagInvoke(TTagInvokeTag<ToErrorAttributeValue>, const T& value)
+std::string TagInvoke(TTagInvokeTag<ToErrorAttributeValue>, const T& value)
{
- return NYson::ConvertToYsonString(value, NYson::EYsonFormat::Text);
+ return std::string(NYson::ConvertToYsonString(value, NYson::EYsonFormat::Text).ToString());
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/misc/error.cpp b/yt/yt/core/misc/error.cpp
index 18394636d5..012f301a6b 100644
--- a/yt/yt/core/misc/error.cpp
+++ b/yt/yt/core/misc/error.cpp
@@ -359,7 +359,7 @@ void Serialize(
}
for (const auto& [key, value] : error.Attributes().ListPairs()) {
fluent
- .Item(key).Value(value);
+ .Item(key).Value(NYson::TYsonString(value));
}
})
.DoIf(!error.InnerErrors().empty(), [&] (auto fluent) {
@@ -398,8 +398,10 @@ void Deserialize(TError& error, const NYTree::INodePtr& node)
auto children = mapNode->GetChildOrThrow(AttributesKey)->AsMap()->GetChildren();
for (const auto& [key, value] : children) {
- // TODO(babenko): migrate to std::string
- error <<= TErrorAttribute(TString(key), ConvertToYsonString(value));
+ // NB(arkady-e1ppa): Serialization may add some attributes in normal yson
+ // format (in legacy versions) thus we have to recovert them into the
+ // text ones in order to make sure that everything is in the text format.
+ error <<= TErrorAttribute(key, ConvertToYsonString(value));
}
error.UpdateOriginAttributes();
@@ -443,7 +445,7 @@ void ToProto(NYT::NProto::TError* protoError, const TError& error)
for (const auto& [key, value] : pairs) {
auto* protoAttribute = protoAttributes->add_attributes();
protoAttribute->set_key(key);
- protoAttribute->set_value(value.ToString());
+ protoAttribute->set_value(value);
}
}
@@ -503,6 +505,8 @@ void FromProto(TError* error, const NYT::NProto::TError& protoError)
error->SetMessage(FromProto<TString>(protoError.message()));
if (protoError.has_attributes()) {
for (const auto& protoAttribute : protoError.attributes().attributes()) {
+ // NB(arkady-e1ppa): Again for compatibility reasons we have to recovert stuff
+ // here as well.
auto key = FromProto<TString>(protoAttribute.key());
auto value = FromProto<TString>(protoAttribute.value());
(*error) <<= TErrorAttribute(key, TYsonString(value));
@@ -607,8 +611,10 @@ void TErrorSerializer::Save(TStreamSaveContext& context, const TError& error)
return lhs.first < rhs.first;
});
for (const auto& [key, value] : attributePairs) {
- Save(context, key);
- Save(context, value);
+ // NB(arkady-e1ppa): For the sake of compatibility we keep the old
+ // serialization format.
+ Save(context, TString(key));
+ Save(context, NYson::TYsonString(value));
}
} else {
Save(context, false);
diff --git a/yt/yt/core/yson/writer.cpp b/yt/yt/core/yson/writer.cpp
index 32e3f1636c..e4e3441ad2 100644
--- a/yt/yt/core/yson/writer.cpp
+++ b/yt/yt/core/yson/writer.cpp
@@ -4,6 +4,8 @@
#include <library/cpp/yt/coding/varint.h>
+#include <library/cpp/yt/error/text_yson.h>
+
#include <util/charset/utf8.h>
#include <util/stream/buffer.h>
@@ -253,7 +255,7 @@ void TYsonWriter::OnDoubleScalar(double value)
Stream_->Write(&value, sizeof(double));
} else {
char buf[256];
- auto str = TStringBuf(buf, NDetail::FloatToStringWithNanInf(value, buf, sizeof(buf)));
+ auto str = TStringBuf(buf, NYT::NDetail::FloatToStringWithNanInf(value, buf, sizeof(buf)));
Stream_->Write(str);
if (str.find('.') == TString::npos && str.find('e') == TString::npos && std::isfinite(value)) {
Stream_->Write(".");
diff --git a/yt/yt/core/ytree/convert-inl.h b/yt/yt/core/ytree/convert-inl.h
index 60bf597941..6d1294f646 100644
--- a/yt/yt/core/ytree/convert-inl.h
+++ b/yt/yt/core/ytree/convert-inl.h
@@ -332,9 +332,9 @@ namespace NYT::NAttributeValueConversionImpl {
template <class T>
requires (!CPrimitiveConvertible<T>)
-T TagInvoke(TFrom<T>, const NYson::TYsonString& value)
+T TagInvoke(TFrom<T>, TStringBuf value)
{
- return NYTree::ConvertTo<T>(value);
+ return NYTree::ConvertTo<T>(NYson::TYsonString(value));
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/ytree/unittests/text_yson_convert_ut.cpp b/yt/yt/core/ytree/unittests/text_yson_convert_ut.cpp
index 75913bed0b..598d1fe613 100644
--- a/yt/yt/core/ytree/unittests/text_yson_convert_ut.cpp
+++ b/yt/yt/core/ytree/unittests/text_yson_convert_ut.cpp
@@ -4,27 +4,36 @@
#include <library/cpp/yt/misc/source_location.h>
-#include <library/cpp/yt/yson_string/convert.h>
+#include <library/cpp/yt/error/text_yson.h>
namespace NYT::NYTree {
namespace {
using namespace NYson;
+using namespace NYT::NDetail;
////////////////////////////////////////////////////////////////////////////////
template <class T>
void CheckEqualConversionToTextYson(const T& value, const TSourceLocation& loc = YT_CURRENT_SOURCE_LOCATION)
{
- EXPECT_EQ(ConvertToTextYsonString(value).AsStringBuf(), ConvertToYsonString(value, EYsonFormat::Text).AsStringBuf())
+ auto smartConvert = [] (const auto& value) {
+ if constexpr (std::constructible_from<TStringBuf, const std::remove_cvref_t<decltype(value)>>) {
+ return ConvertToTextYsonString(TStringBuf(value));
+ } else {
+ return ConvertToTextYsonString(value);
+ }
+ };
+ EXPECT_EQ(smartConvert(value), ConvertToYsonString(value, EYsonFormat::Text).AsStringBuf())
<< NYT::Format("At %v", loc);
}
template <class T, class U>
void CheckEqualConversionToFromTextYson(const U& value, const TSourceLocation& loc = YT_CURRENT_SOURCE_LOCATION)
{
- auto yson = ConvertToTextYsonString(value);
- EXPECT_EQ(ConvertFromTextYsonString<T>(yson), ConvertTo<T>(yson))
+ auto str = ConvertToTextYsonString(value);
+ auto yson = TYsonString(str);
+ EXPECT_EQ(ConvertFromTextYsonString<T>(str), ConvertTo<T>(yson))
<< NYT::Format("At %v", loc);
}
@@ -32,7 +41,7 @@ template <class T>
void CheckEqualConversionFromTextYson(TStringBuf value, const TSourceLocation& loc = YT_CURRENT_SOURCE_LOCATION)
{
NYson::TYsonString yson(value);
- EXPECT_EQ(ConvertTo<T>(yson), ConvertTo<T>(yson))
+ EXPECT_EQ(ConvertFromTextYsonString<T>(value), ConvertTo<T>(yson))
<< NYT::Format("At %v", loc);
}
@@ -203,66 +212,66 @@ TEST(TTextYsonConvertTest, ConvertFromTextTypeMissmatch)
CheckEqualConversionFromTextYson<bool>("1u");
CheckEqualConversionFromTextYson<bool>("0u");
- CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString("true").AsStringBuf());
- CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString("false").AsStringBuf());
- CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString("1").AsStringBuf());
- CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString("0").AsStringBuf());
+ CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString(TStringBuf("true")));
+ CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString(TStringBuf("false")));
+ CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString(TStringBuf("1")));
+ CheckEqualConversionFromTextYson<bool>(ConvertToTextYsonString(TStringBuf("0")));
}
TEST(TTextYsonConvertTest, ConvertFromTextYsonStringThrowBasicCases)
{
auto fromPayload = [] (const auto& value) {
- return NYson::TYsonString(TString(value));
+ return TYsonString(TString(value));
};
// Overflow.
- EXPECT_ANY_THROW(ConvertFromTextYsonString<i8>(fromPayload("123123123213")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<i8>("123123123213"));
EXPECT_ANY_THROW(ConvertTo<i8>(fromPayload("123123123213")));
// Negative.
- EXPECT_ANY_THROW(ConvertFromTextYsonString<ui64>(fromPayload("-123")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<ui64>("-123"));
EXPECT_ANY_THROW(ConvertTo<ui64>(fromPayload("-123")));
// Non-numeric.
- EXPECT_ANY_THROW(ConvertFromTextYsonString<i64>(fromPayload("haha")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<i64>(fromPayload("123qq")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<i64>(fromPayload("-123u")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<i64>("haha"));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<i64>("123qq"));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<i64>("-123u"));
EXPECT_ANY_THROW(ConvertTo<i64>(fromPayload("haha")));
EXPECT_ANY_THROW(ConvertTo<i64>(fromPayload("123qq")));
EXPECT_ANY_THROW(ConvertTo<i64>(fromPayload("-123u")));
// Big positive to bool
- EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>(fromPayload("42")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>("42"));
EXPECT_ANY_THROW(ConvertTo<bool>(fromPayload("42")));
// Garbage to bool
- EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>(fromPayload("%falsse")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>("%falsse"));
EXPECT_ANY_THROW(ConvertTo<bool>(fromPayload("%falsse")));
// Wrong string to bool
- EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>(fromPayload("\"True\"")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>(fromPayload("\"False\"")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>(fromPayload("\"1u\"")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>(fromPayload("\"0u\"")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>("\"True\""));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>("\"False\""));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>("\"1u\""));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<bool>("\"0u\""));
EXPECT_ANY_THROW(ConvertTo<bool>(fromPayload("\"True\"")));
EXPECT_ANY_THROW(ConvertTo<bool>(fromPayload("\"False\"")));
EXPECT_ANY_THROW(ConvertTo<bool>(fromPayload("\"1u\"")));
EXPECT_ANY_THROW(ConvertTo<bool>(fromPayload("\"0u\"")));
// Wrong string to string
- EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(fromPayload("")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(fromPayload("\"")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(fromPayload("haha\"")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(fromPayload("\'oops\'")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(""));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>("\""));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>("haha\""));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>("\'oops\'"));
EXPECT_ANY_THROW(ConvertTo<std::string>(fromPayload("")));
EXPECT_ANY_THROW(ConvertTo<std::string>(fromPayload("\"")));
EXPECT_ANY_THROW(ConvertTo<std::string>(fromPayload("haha\"")));
EXPECT_ANY_THROW(ConvertTo<std::string>(fromPayload("\'oops\'")));
// Wrong literal to double
- EXPECT_ANY_THROW(ConvertFromTextYsonString<double>(fromPayload("%%")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(fromPayload("%42inf")));
- EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>(fromPayload("%NaaN")));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<double>("%%"));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>("%42inf"));
+ EXPECT_ANY_THROW(ConvertFromTextYsonString<std::string>("%NaaN"));
EXPECT_ANY_THROW(ConvertTo<double>(fromPayload("%%")));
EXPECT_ANY_THROW(ConvertTo<std::string>(fromPayload("%42inf")));
EXPECT_ANY_THROW(ConvertTo<std::string>(fromPayload("%NaaN")));