123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- #include "convert.h"
- #include "format.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/stream/mem.h>
- namespace NYT::NYson {
- ////////////////////////////////////////////////////////////////////////////////
- template <>
- TYsonString ConvertToYsonString<i8>(const i8& value)
- {
- return ConvertToYsonString(static_cast<i64>(value));
- }
- template <>
- TYsonString ConvertToYsonString<i32>(const i32& value)
- {
- return ConvertToYsonString(static_cast<i64>(value));
- }
- template <>
- TYsonString ConvertToYsonString<i64>(const i64& value)
- {
- std::array<char, 1 + MaxVarInt64Size> buffer;
- auto* ptr = buffer.data();
- *ptr++ = NDetail::Int64Marker;
- ptr += WriteVarInt64(ptr, value);
- return TYsonString(TStringBuf(buffer.data(), ptr - buffer.data()));
- }
- template <>
- TYsonString ConvertToYsonString<ui8>(const ui8& value)
- {
- return ConvertToYsonString(static_cast<ui64>(value));
- }
- template <>
- TYsonString ConvertToYsonString<ui32>(const ui32& value)
- {
- return ConvertToYsonString(static_cast<ui64>(value));
- }
- template <>
- TYsonString ConvertToYsonString<ui64>(const ui64& value)
- {
- std::array<char, 1 + MaxVarInt64Size> buffer;
- auto* ptr = buffer.data();
- *ptr++ = NDetail::Uint64Marker;
- ptr += WriteVarUint64(ptr, value);
- return TYsonString(TStringBuf(buffer.data(), ptr - buffer.data()));
- }
- template <>
- TYsonString ConvertToYsonString<TString>(const TString& value)
- {
- return ConvertToYsonString(static_cast<TStringBuf>(value));
- }
- struct TConvertStringToYsonStringTag
- { };
- template <>
- TYsonString ConvertToYsonString<TStringBuf>(const TStringBuf& value)
- {
- auto buffer = TSharedMutableRef::Allocate<TConvertStringToYsonStringTag>(
- 1 + MaxVarInt64Size + value.length(),
- {.InitializeStorage = false});
- auto* ptr = buffer.Begin();
- *ptr++ = NDetail::StringMarker;
- ptr += WriteVarInt64(ptr, static_cast<i64>(value.length()));
- ::memcpy(ptr, value.data(), value.length());
- ptr += value.length();
- return TYsonString(buffer.Slice(buffer.Begin(), ptr));
- }
- TYsonString ConvertToYsonString(const char* value)
- {
- return ConvertToYsonString(TStringBuf(value));
- }
- template <>
- TYsonString ConvertToYsonString<float>(const float& value)
- {
- return ConvertToYsonString(static_cast<double>(value));
- }
- template <>
- TYsonString ConvertToYsonString<double>(const double& value)
- {
- std::array<char, 1 + sizeof(double)> buffer;
- auto* ptr = buffer.data();
- *ptr++ = NDetail::DoubleMarker;
- ::memcpy(ptr, &value, sizeof(value));
- ptr += sizeof(value);
- return TYsonString(TStringBuf(buffer.data(), ptr - buffer.data()));
- }
- template <>
- TYsonString ConvertToYsonString<bool>(const bool& value)
- {
- char ch = value ? NDetail::TrueMarker : NDetail::FalseMarker;
- return TYsonString(TStringBuf(&ch, 1));
- }
- template <>
- TYsonString ConvertToYsonString<TInstant>(const TInstant& value)
- {
- return ConvertToYsonString(value.ToString());
- }
- template <>
- TYsonString ConvertToYsonString<TDuration>(const TDuration& value)
- {
- return ConvertToYsonString(value.MilliSeconds());
- }
- template <>
- TYsonString ConvertToYsonString<TGuid>(const TGuid& value)
- {
- std::array<char, MaxGuidStringSize> guidBuffer;
- auto guidLength = WriteGuidToBuffer(guidBuffer.data(), value) - guidBuffer.data();
- std::array<char, 1 + MaxVarInt64Size + MaxGuidStringSize> ysonBuffer;
- auto* ptr = ysonBuffer.data();
- *ptr++ = NDetail::StringMarker;
- ptr += WriteVarInt64(ptr, static_cast<i64>(guidLength));
- ::memcpy(ptr, guidBuffer.data(), guidLength);
- ptr += guidLength;
- return TYsonString(TStringBuf(ysonBuffer.data(), ptr - ysonBuffer.data()));
- }
- ////////////////////////////////////////////////////////////////////////////////
- namespace {
- TString FormatUnexpectedMarker(char ch)
- {
- switch (ch) {
- case NDetail::BeginListSymbol:
- return "list";
- case NDetail::BeginMapSymbol:
- return "map";
- case NDetail::BeginAttributesSymbol:
- return "attributes";
- case NDetail::EntitySymbol:
- return "\"entity\" literal";
- case NDetail::StringMarker:
- return "\"string\" literal";
- case NDetail::Int64Marker:
- return "\"int64\" literal";
- case NDetail::DoubleMarker:
- return "\"double\" literal";
- case NDetail::FalseMarker:
- case NDetail::TrueMarker:
- return "\"boolean\" literal";
- case NDetail::Uint64Marker:
- return "\"uint64\" literal";
- default:
- return Format("unexpected symbol %qv", ch);
- }
- }
- i64 ParseInt64FromYsonString(const TYsonStringBuf& str)
- {
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
- TMemoryInput input(strBuf.data(), strBuf.length());
- char ch;
- if (!input.ReadChar(ch)) {
- throw TYsonLiteralParseException("Missing type marker");
- }
- if (ch != NDetail::Int64Marker) {
- throw TYsonLiteralParseException(Format("Unexpected %v",
- FormatUnexpectedMarker(ch)));
- }
- i64 result;
- try {
- ReadVarInt64(&input, &result);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Failed to decode \"int64\" value");
- }
- return result;
- }
- ui64 ParseUint64FromYsonString(const TYsonStringBuf& str)
- {
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
- TMemoryInput input(strBuf.data(), strBuf.length());
- char ch;
- if (!input.ReadChar(ch)) {
- throw TYsonLiteralParseException("Missing type marker");
- }
- if (ch != NDetail::Uint64Marker) {
- throw TYsonLiteralParseException(Format("Unexpected %v",
- FormatUnexpectedMarker(ch)));
- }
- ui64 result;
- try {
- ReadVarUint64(&input, &result);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Failed to decode \"uint64\" value");
- }
- return result;
- }
- TString ParseStringFromYsonString(const TYsonStringBuf& str)
- {
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
- TMemoryInput input(strBuf.data(), strBuf.length());
- char ch;
- if (!input.ReadChar(ch)) {
- throw TYsonLiteralParseException("Missing type marker");
- }
- if (ch != NDetail::StringMarker) {
- throw TYsonLiteralParseException(Format("Unexpected %v",
- FormatUnexpectedMarker(ch)));
- }
- i64 length;
- try {
- ReadVarInt64(&input, &length);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Failed to decode string length");
- }
- if (length < 0) {
- throw TYsonLiteralParseException(Format("Negative string length ",
- length));
- }
- if (static_cast<i64>(input.Avail()) != length) {
- throw TYsonLiteralParseException(Format("Incorrect remaining string length: expected %v, got %v",
- length,
- input.Avail()));
- }
- TString result;
- result.ReserveAndResize(length);
- YT_VERIFY(static_cast<i64>(input.Read(result.Detach(), length)) == length);
- return result;
- }
- double ParseDoubleFromYsonString(const TYsonStringBuf& str)
- {
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
- TMemoryInput input(strBuf.data(), strBuf.length());
- char ch;
- if (!input.ReadChar(ch)) {
- throw TYsonLiteralParseException("Missing type marker");
- }
- if (ch != NDetail::DoubleMarker) {
- throw TYsonLiteralParseException(Format("Unexpected %v",
- FormatUnexpectedMarker(ch)));
- }
- if (input.Avail() != sizeof(double)) {
- throw TYsonLiteralParseException(Format("Incorrect remaining string length: expected %v, got %v",
- sizeof(double),
- input.Avail()));
- }
- double result;
- YT_VERIFY(input.Read(&result, sizeof(result)));
- return result;
- }
- } // namespace
- #define PARSE(type, underlyingType) \
- template <> \
- type ConvertFromYsonString<type>(const TYsonStringBuf& str) \
- { \
- try { \
- return CheckedIntegralCast<type>(Parse ## underlyingType ## FromYsonString(str)); \
- } catch (const std::exception& ex) { \
- throw TYsonLiteralParseException(ex, "Error parsing \"" #type "\" value from YSON"); \
- } \
- }
- PARSE(i8, Int64 )
- PARSE(i16, Int64 )
- PARSE(i32, Int64 )
- PARSE(i64, Int64 )
- PARSE(ui8, Uint64)
- PARSE(ui16, Uint64)
- PARSE(ui32, Uint64)
- PARSE(ui64, Uint64)
- #undef PARSE
- template <>
- TString ConvertFromYsonString<TString>(const TYsonStringBuf& str)
- {
- try {
- return ParseStringFromYsonString(str);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"string\" value from YSON");
- }
- }
- template <>
- float ConvertFromYsonString<float>(const TYsonStringBuf& str)
- {
- try {
- return static_cast<float>(ParseDoubleFromYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"float\" value from YSON");
- }
- }
- template <>
- double ConvertFromYsonString<double>(const TYsonStringBuf& str)
- {
- try {
- return ParseDoubleFromYsonString(str);
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"double\" value from YSON");
- }
- }
- template <>
- bool ConvertFromYsonString<bool>(const TYsonStringBuf& str)
- {
- try {
- YT_ASSERT(str.GetType() == EYsonType::Node);
- auto strBuf = str.AsStringBuf();
- TMemoryInput input(strBuf.data(), strBuf.length());
- char ch;
- if (!input.ReadChar(ch)) {
- throw TYsonLiteralParseException("Missing type marker");
- }
- if (ch != NDetail::TrueMarker && ch != NDetail::FalseMarker) {
- throw TYsonLiteralParseException(Format("Unexpected %v",
- FormatUnexpectedMarker(ch)));
- }
- return ch == NDetail::TrueMarker;
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"boolean\" value from YSON");
- }
- }
- template <>
- TInstant ConvertFromYsonString<TInstant>(const TYsonStringBuf& str)
- {
- try {
- return TInstant::ParseIso8601(ParseStringFromYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"instant\" value from YSON");
- }
- }
- template <>
- TDuration ConvertFromYsonString<TDuration>(const TYsonStringBuf& str)
- {
- try {
- return TDuration::MilliSeconds(ParseUint64FromYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"duration\" value from YSON");
- }
- }
- template <>
- TGuid ConvertFromYsonString<TGuid>(const TYsonStringBuf& str)
- {
- try {
- return TGuid::FromString(ParseStringFromYsonString(str));
- } catch (const std::exception& ex) {
- throw TYsonLiteralParseException(ex, "Error parsing \"guid\" value from YSON");
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- } // namespace NYT::NYson
|