diff options
author | dgolear <dgolear@yandex-team.com> | 2025-01-21 17:15:56 +0300 |
---|---|---|
committer | dgolear <dgolear@yandex-team.com> | 2025-01-21 17:32:49 +0300 |
commit | 103573103ee8ce82c657c35d2e80e21e6c3dcf7f (patch) | |
tree | de3de184f59d3f164b561a71a7a6444444c6e9a6 | |
parent | 471e5899d566a5fa8fe1f8b6c90e6d5e81f15756 (diff) | |
download | ydb-103573103ee8ce82c657c35d2e80e21e6c3dcf7f.tar.gz |
YT: Move IYsonBuilder from ORM to core yson/ library
commit_hash:3d8bdd14cc5420209534498f0b1e61dea8e4aa1e
-rw-r--r-- | yt/yt/core/ya.make | 1 | ||||
-rw-r--r-- | yt/yt/core/yson/unittests/ya.make | 1 | ||||
-rw-r--r-- | yt/yt/core/yson/unittests/yson_builder_ut.cpp | 87 | ||||
-rw-r--r-- | yt/yt/core/yson/yson_builder.cpp | 97 | ||||
-rw-r--r-- | yt/yt/core/yson/yson_builder.h | 76 |
5 files changed, 262 insertions, 0 deletions
diff --git a/yt/yt/core/ya.make b/yt/yt/core/ya.make index 857e56920b..a958bb1c6a 100644 --- a/yt/yt/core/ya.make +++ b/yt/yt/core/ya.make @@ -269,6 +269,7 @@ SRCS( yson/string_merger.cpp yson/ypath_designated_consumer.cpp yson/ypath_filtering_consumer.cpp + yson/yson_builder.cpp yson/depth_limiting_yson_consumer.cpp yson/list_verb_lazy_yson_consumer.cpp yson/attributes_stripper.cpp diff --git a/yt/yt/core/yson/unittests/ya.make b/yt/yt/core/yson/unittests/ya.make index 59a807fca4..8f8fc7dfc0 100644 --- a/yt/yt/core/yson/unittests/ya.make +++ b/yt/yt/core/yson/unittests/ya.make @@ -14,6 +14,7 @@ SRCS( protobuf_yson_ut.cpp ypath_designated_yson_consumer_ut.cpp ypath_filtering_yson_consumer_ut.cpp + yson_builder_ut.cpp yson_parser_ut.cpp yson_pull_parser_ut.cpp yson_token_writer_ut.cpp diff --git a/yt/yt/core/yson/unittests/yson_builder_ut.cpp b/yt/yt/core/yson/unittests/yson_builder_ut.cpp new file mode 100644 index 0000000000..c3353a56de --- /dev/null +++ b/yt/yt/core/yson/unittests/yson_builder_ut.cpp @@ -0,0 +1,87 @@ +#include <yt/yt/core/yson/consumer.h> +#include <yt/yt/core/yson/string.h> +#include <yt/yt/core/yson/yson_builder.h> + +#include <yt/yt/core/test_framework/framework.h> + +namespace NYT::NYson { +namespace { + +//////////////////////////////////////////////////////////////////////////////// + +TEST(TYsonStringBuilderTest, Simple) +{ + NYson::TYsonStringBuilder builder; + builder->OnStringScalar("some_scalar"); + ASSERT_EQ(builder.Flush().ToString(), TString{"\1\x16some_scalar"}); + ASSERT_TRUE(builder.IsEmpty()); +} + +TEST(TYsonStringBuilderTest, Reusing) +{ + NYson::TYsonStringBuilder builder; + builder->OnStringScalar("some_scalar1"); + ASSERT_EQ(builder.Flush().ToString(), TString{"\1\x18some_scalar1"}); + ASSERT_TRUE(builder.IsEmpty()); + + builder->OnStringScalar("some_scalar2"); + ASSERT_EQ(builder.Flush().ToString(), TString{"\1\x18some_scalar2"}); + ASSERT_TRUE(builder.IsEmpty()); +} + +TEST(TYsonStringBuilderTest, Checkpoints) +{ + NYson::TYsonStringBuilder builder; + builder->OnStringScalar("some_scalar"); + + auto checkpoint = builder.CreateCheckpoint(); + builder.CreateCheckpoint(); + builder.RestoreCheckpoint(checkpoint); + builder.RestoreCheckpoint(checkpoint); + + ASSERT_EQ(builder.Flush().ToString(), TString{"\1\x16some_scalar"}); + ASSERT_TRUE(builder.IsEmpty()); +} + +TEST(TYsonStringBuilderTest, MapCheckpoints) +{ + NYson::TYsonStringBuilder builder(NYson::EYsonFormat::Text); + + builder->OnBeginMap(); + + builder->OnKeyedItem("key1"); + builder->OnEntity(); + + auto checkpoint = builder.CreateCheckpoint(); + builder->OnKeyedItem("key2"); + builder->OnEntity(); + builder.RestoreCheckpoint(checkpoint); + + builder->OnEndMap(); + + ASSERT_EQ(builder.Flush().ToString(), TString{R"({"key1"=#;})"}); +} + +//////////////////////////////////////////////////////////////////////////////// + +TEST(TYsonBuilderTest, Forwarding) +{ + NYson::TYsonStringBuilder stringBuilder(NYson::EYsonFormat::Text); + NYson::TYsonBuilder builder( + NYson::EYsonBuilderForwardingPolicy::Forward, + &stringBuilder, + stringBuilder.GetConsumer()); + builder->OnBeginMap(); + auto checkpoint = builder.CreateCheckpoint(); + builder->OnKeyedItem("key"); + builder->OnEntity(); + builder.RestoreCheckpoint(checkpoint); + builder->OnEndMap(); + + ASSERT_EQ(stringBuilder.Flush().ToString(), TString{R"({})"}); +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace +} // namespace NYT::NYson diff --git a/yt/yt/core/yson/yson_builder.cpp b/yt/yt/core/yson/yson_builder.cpp new file mode 100644 index 0000000000..a17b9b8772 --- /dev/null +++ b/yt/yt/core/yson/yson_builder.cpp @@ -0,0 +1,97 @@ +#include "yson_builder.h" + +#include "writer.h" + +namespace NYT::NYson { + +//////////////////////////////////////////////////////////////////////////////// + +IYsonConsumer* IYsonBuilder::operator->() +{ + return GetConsumer(); +} + +//////////////////////////////////////////////////////////////////////////////// + +TYsonStringBuilder::TYsonStringBuilder(EYsonFormat format, EYsonType type, bool enableRaw) + : Output_(ValueString_) + , Writer_(CreateYsonWriter(&Output_, format, type, enableRaw)) +{ } + +IYsonConsumer* TYsonStringBuilder::GetConsumer() +{ + return Writer_.get(); +} + +IYsonBuilder::TCheckpoint TYsonStringBuilder::CreateCheckpoint() +{ + Writer_->Flush(); + return IYsonBuilder::TCheckpoint(std::ssize(ValueString_)); +} + +void TYsonStringBuilder::RestoreCheckpoint(IYsonBuilder::TCheckpoint checkpoint) +{ + Writer_->Flush(); + int checkpointSize = checkpoint.Underlying(); + YT_VERIFY(checkpointSize >= 0 && checkpointSize <= std::ssize(ValueString_)); + ValueString_.resize(static_cast<size_t>(checkpointSize)); +} + +TYsonString TYsonStringBuilder::Flush() +{ + Writer_->Flush(); + auto result = TYsonString(ValueString_); + ValueString_.clear(); + return result; +} + +bool TYsonStringBuilder::IsEmpty() +{ + Writer_->Flush(); + return ValueString_.empty(); +} + +//////////////////////////////////////////////////////////////////////////////// + +TYsonBuilder::TYsonBuilder( + EYsonBuilderForwardingPolicy policy, + IYsonBuilder* underlying, + IYsonConsumer* consumer) + : Policy_(policy) + , Underlying_(underlying) + , Consumer_(consumer) +{ } + +IYsonConsumer* TYsonBuilder::GetConsumer() +{ + return Consumer_; +} + +IYsonBuilder::TCheckpoint TYsonBuilder::CreateCheckpoint() +{ + switch (Policy_) { + case EYsonBuilderForwardingPolicy::Forward: + return Underlying_->CreateCheckpoint(); + case EYsonBuilderForwardingPolicy::Crash: + return IYsonBuilder::TCheckpoint{}; + case EYsonBuilderForwardingPolicy::Ignore: + return IYsonBuilder::TCheckpoint{}; + } +} + +void TYsonBuilder::RestoreCheckpoint(TCheckpoint checkpoint) +{ + switch (Policy_) { + case EYsonBuilderForwardingPolicy::Forward: + Underlying_->RestoreCheckpoint(checkpoint); + break; + case EYsonBuilderForwardingPolicy::Crash: + YT_ABORT(); + case EYsonBuilderForwardingPolicy::Ignore: + break; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NYson diff --git a/yt/yt/core/yson/yson_builder.h b/yt/yt/core/yson/yson_builder.h new file mode 100644 index 0000000000..5f483124e8 --- /dev/null +++ b/yt/yt/core/yson/yson_builder.h @@ -0,0 +1,76 @@ +#pragma once + +#include "public.h" + +#include <library/cpp/yt/misc/strong_typedef.h> + +namespace NYT::NYson { + +//////////////////////////////////////////////////////////////////////////////// + +struct IYsonBuilder +{ + YT_DEFINE_STRONG_TYPEDEF(TCheckpoint, int); + + virtual ~IYsonBuilder() = default; + + virtual IYsonConsumer* GetConsumer() = 0; + virtual TCheckpoint CreateCheckpoint() = 0; + virtual void RestoreCheckpoint(TCheckpoint checkpoint) = 0; + + IYsonConsumer* operator->(); +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TYsonStringBuilder + : public IYsonBuilder +{ +public: + TYsonStringBuilder( + NYson::EYsonFormat format = NYson::EYsonFormat::Binary, + NYson::EYsonType type = NYson::EYsonType::Node, + bool enableRaw = true); + + NYson::IYsonConsumer* GetConsumer() override; + IYsonBuilder::TCheckpoint CreateCheckpoint() override; + void RestoreCheckpoint(IYsonBuilder::TCheckpoint checkpoint) override; + + NYson::TYsonString Flush(); + bool IsEmpty(); + +private: + TString ValueString_; + TStringOutput Output_; + const std::unique_ptr<NYson::IFlushableYsonConsumer> Writer_; +}; + +//////////////////////////////////////////////////////////////////////////////// + +DEFINE_ENUM(EYsonBuilderForwardingPolicy, + (Forward) + (Ignore) + (Crash) +); + +//////////////////////////////////////////////////////////////////////////////// + +class TYsonBuilder + : public IYsonBuilder +{ +public: + TYsonBuilder(EYsonBuilderForwardingPolicy policy, IYsonBuilder* underlying, IYsonConsumer* consumer); + + IYsonConsumer* GetConsumer() override; + IYsonBuilder::TCheckpoint CreateCheckpoint() override; + void RestoreCheckpoint(TCheckpoint checkpoint) override; + +private: + const EYsonBuilderForwardingPolicy Policy_; + IYsonBuilder* const Underlying_; + NYson::IYsonConsumer* const Consumer_; +}; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NYson |