diff options
author | babenko <[email protected]> | 2024-08-15 14:13:45 +0300 |
---|---|---|
committer | babenko <[email protected]> | 2024-08-15 14:26:08 +0300 |
commit | 1675f48e0ce19ee911fd1131b20198ad0e91fd97 (patch) | |
tree | 7e9f1c9cdb2747ce89697c029a3b2b055f368f73 | |
parent | 7ed8c594b8533538dfdcc354f6b38c7c84919189 (diff) |
DeprecatedField -> VirtualField; also support saving virtual fields
488c5618adaa789790af173bbb63fb9354af45a8
-rw-r--r-- | yt/yt/core/phoenix/descriptors.cpp | 6 | ||||
-rw-r--r-- | yt/yt/core/phoenix/descriptors.h | 2 | ||||
-rw-r--r-- | yt/yt/core/phoenix/load.cpp | 4 | ||||
-rw-r--r-- | yt/yt/core/phoenix/schemas.cpp | 3 | ||||
-rw-r--r-- | yt/yt/core/phoenix/schemas.h | 1 | ||||
-rw-r--r-- | yt/yt/core/phoenix/type_decl-inl.h | 4 | ||||
-rw-r--r-- | yt/yt/core/phoenix/type_def-inl.h | 256 | ||||
-rw-r--r-- | yt/yt/core/phoenix/unittests/phoenix_ut.cpp | 62 |
8 files changed, 273 insertions, 65 deletions
diff --git a/yt/yt/core/phoenix/descriptors.cpp b/yt/yt/core/phoenix/descriptors.cpp index b961263e7f4..90ee72f7fcc 100644 --- a/yt/yt/core/phoenix/descriptors.cpp +++ b/yt/yt/core/phoenix/descriptors.cpp @@ -18,11 +18,6 @@ TFieldTag TFieldDescriptor::GetTag() const return Tag_; } -bool TFieldDescriptor::IsDeprecated() const -{ - return Deprecated_; -} - const TFieldSchemaPtr& TFieldDescriptor::GetSchema() const { std::call_once( @@ -31,7 +26,6 @@ const TFieldSchemaPtr& TFieldDescriptor::GetSchema() const Schema_ = New<TFieldSchema>(); Schema_->Name = Name_; Schema_->Tag = Tag_; - Schema_->Deprecated = Deprecated_; }); return Schema_; } diff --git a/yt/yt/core/phoenix/descriptors.h b/yt/yt/core/phoenix/descriptors.h index ea6a803a625..1ec630a75df 100644 --- a/yt/yt/core/phoenix/descriptors.h +++ b/yt/yt/core/phoenix/descriptors.h @@ -29,7 +29,6 @@ class TFieldDescriptor public: const TString& GetName() const; TFieldTag GetTag() const; - bool IsDeprecated() const; const TFieldSchemaPtr& GetSchema() const; @@ -39,7 +38,6 @@ private: TString Name_; TFieldTag Tag_; - bool Deprecated_ = false; int MinVersion_ = std::numeric_limits<int>::min(); int MaxVersion_ = std::numeric_limits<int>::max(); diff --git a/yt/yt/core/phoenix/load.cpp b/yt/yt/core/phoenix/load.cpp index 5e8c72641de..d8a48b879f7 100644 --- a/yt/yt/core/phoenix/load.cpp +++ b/yt/yt/core/phoenix/load.cpp @@ -30,10 +30,6 @@ bool AreFieldSchemasEquivalent( if (lhsFieldDescriptor->GetTag() != rhsFieldSchema->Tag) { return false; } - - if (lhsFieldDescriptor->IsDeprecated() != rhsFieldSchema->Deprecated) { - return false; - } } return true; diff --git a/yt/yt/core/phoenix/schemas.cpp b/yt/yt/core/phoenix/schemas.cpp index bdf5fcb0e6b..f5e6c119cda 100644 --- a/yt/yt/core/phoenix/schemas.cpp +++ b/yt/yt/core/phoenix/schemas.cpp @@ -10,9 +10,6 @@ void TFieldSchema::Register(TRegistrar registrar) { registrar.Parameter("name", &TThis::Name); registrar.Parameter("tag", &TThis::Tag); - registrar.Parameter("deprecated", &TThis::Deprecated) - .Default(false) - .DontSerializeDefault(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/phoenix/schemas.h b/yt/yt/core/phoenix/schemas.h index c418919c5b7..7de235b18cd 100644 --- a/yt/yt/core/phoenix/schemas.h +++ b/yt/yt/core/phoenix/schemas.h @@ -13,7 +13,6 @@ struct TFieldSchema { TString Name; TFieldTag Tag; - bool Deprecated; REGISTER_YSON_STRUCT(TFieldSchema); static void Register(TRegistrar registrar); diff --git a/yt/yt/core/phoenix/type_decl-inl.h b/yt/yt/core/phoenix/type_decl-inl.h index e458acf303a..3d5ed37aeba 100644 --- a/yt/yt/core/phoenix/type_decl-inl.h +++ b/yt/yt/core/phoenix/type_decl-inl.h @@ -28,8 +28,8 @@ private: \ template <class TThis, class TContext> \ friend std::unique_ptr<::NYT::NPhoenix2::NDetail::TRuntimeTypeLoadSchedule<TThis, TContext>> NYT::NPhoenix2::NDetail::BuildRuntimeTypeLoadSchedule( \ const ::NYT::NPhoenix2::NDetail::TTypeLoadSchedule* schedule); \ - template <auto Member, class TThis, class TContext, class TFieldSerializer> \ - friend class ::NYT::NPhoenix2::NDetail::TFieldLoadRegistrar + template <class TThis> \ + friend struct ::NYT::NPhoenix2::NDetail::TTraits #define PHOENIX_DECLARE_TYPE__IMPL(type, typeTagValue, saveLoadModifier) \ PHOENIX_DECLARE_TYPE__PROLOGUE(type, typeTagValue); \ diff --git a/yt/yt/core/phoenix/type_def-inl.h b/yt/yt/core/phoenix/type_def-inl.h index 774b55e7ae5..32e01b28c43 100644 --- a/yt/yt/core/phoenix/type_def-inl.h +++ b/yt/yt/core/phoenix/type_def-inl.h @@ -77,6 +77,25 @@ namespace NYT::NPhoenix2::NDetail { //////////////////////////////////////////////////////////////////////////////// +template <class TThis, class TContext> +using TFieldMissingHandler = void (*)(TThis*, TContext&); + +template <class TThis, class TContext> +using TFieldLoadHandler = void (*)(TThis*, TContext&); + +template <class TThis, class TContext> +using TFieldSaveHandler = void (*)(const TThis*, TContext&); + +//////////////////////////////////////////////////////////////////////////////// + +template <class TThis> +struct TTraits +{ + using TVersion = decltype(std::declval<typename TThis::TLoadContextImpl>().GetVersion()); +}; + +//////////////////////////////////////////////////////////////////////////////// + #define PHOENIX_REGISTRAR_NODISCARD [[nodiscard("Did you forget to call operator()?")]] class PHOENIX_REGISTRAR_NODISCARD TDummyFieldRegistrar @@ -117,7 +136,18 @@ public: } template <TFieldTag::TUnderlying TagValue> - TDummyFieldRegistrar DeprecatedField(auto&& /*name*/, auto&& /*handler*/) + TDummyFieldRegistrar VirtualField( + auto&& /*name*/, + auto&& /*loadHandler*/) + { + return {}; + } + + template <TFieldTag::TUnderlying TagValue> + TDummyFieldRegistrar VirtualField( + auto&& /*name*/, + auto&& /*loadHandler*/, + auto&& /*saveHandler*/) { return {}; } @@ -156,13 +186,24 @@ public: template <TFieldTag::TUnderlying TagValue, auto Member> auto Field(TString name) { - return DoField<TagValue>(std::move(name), /*deprecated*/ false); + return DoField<TagValue>(std::move(name)); } template <TFieldTag::TUnderlying TagValue> - auto DeprecatedField(TString name, auto&& /*handler*/) + auto VirtualField( + TString name, + auto&& /*loadHandler*/) { - return DoField<TagValue>(std::move(name), /*deprecated*/ true); + return DoField<TagValue>(std::move(name)); + } + + template <TFieldTag::TUnderlying TagValue> + auto VirtualField( + TString name, + auto&& loadHandler, + auto&& /*saveHandler*/) + { + return VirtualField<TagValue>(std::move(name), loadHandler); } template <class TBase> @@ -177,12 +218,11 @@ private: std::unique_ptr<TTypeDescriptor> TypeDescriptor_ = std::make_unique<TTypeDescriptor>(); template <TFieldTag::TUnderlying TagValue> - auto DoField(TString name, bool deprecated) + auto DoField(TString name) { auto fieldDescriptor = std::make_unique<TFieldDescriptor>(); fieldDescriptor->Name_ = std::move(name); fieldDescriptor->Tag_ = TFieldTag(TagValue); - fieldDescriptor->Deprecated_ = deprecated; TypeDescriptor_->Fields_.push_back(std::move(fieldDescriptor)); return TDummyFieldRegistrar(); } @@ -297,6 +337,51 @@ private: }; template <class TThis, class TContext> +class PHOENIX_REGISTRAR_NODISCARD TVirtualFieldSaveRegistrar +{ +public: + TVirtualFieldSaveRegistrar( + const TThis* this_, + TContext& context, + TFieldSaveHandler<TThis, TContext> saveHandler) + : This_(this_) + , Context_(context) + , SaveHandler_(saveHandler) + { } + + TVirtualFieldSaveRegistrar(TVirtualFieldSaveRegistrar<TThis, TContext>&& other) + : This_(other.This_) + , Context_(other.Context_) + , SaveHandler_(other.SaveHandler_) + { } + + auto SinceVersion(auto /*version*/) && + { + return TVirtualFieldSaveRegistrar(std::move(*this)); + } + + auto InVersions(auto /*filter*/) && + { + return TVirtualFieldSaveRegistrar(std::move(*this)); + } + + auto WhenMissing(auto&& /*handler*/) && + { + return TVirtualFieldSaveRegistrar(std::move(*this)); + } + + void operator()() && + { + SaveHandler_(This_, Context_); + } + +private: + const TThis* const This_; + TContext& Context_; + const TFieldSaveHandler<TThis, TContext> SaveHandler_; +}; + +template <class TThis, class TContext> class TSaveFieldsRegistrar : public TTypeRegistrarBase { @@ -314,6 +399,26 @@ public: Context_); } + template <TFieldTag::TUnderlying TagValue> + auto VirtualField( + auto&& /*name*/, + auto&& /*loadHandler*/) + { + return TDummyFieldRegistrar(); + } + + template <TFieldTag::TUnderlying TagValue> + auto VirtualField( + auto&& /*name*/, + auto&& /*loadHandler*/, + TFieldSaveHandler<TThis, TContext> saveHandler) + { + return TVirtualFieldSaveRegistrar<TThis, TContext>( + This_, + Context_, + saveHandler); + } + private: const TThis* const This_; TContext& Context_; @@ -353,7 +458,10 @@ template <auto Member, class TThis, class TContext, class TFieldSerializer> class PHOENIX_REGISTRAR_NODISCARD TFieldLoadRegistrar { public: - TFieldLoadRegistrar(TThis* this_, TContext& context, TStringBuf name) + TFieldLoadRegistrar( + TThis* this_, + TContext& context, + TStringBuf name) : This_(this_) , Context_(context) , Name_(name) @@ -369,7 +477,7 @@ public: , MissingHandler_(other.MissingHandler_) { } - using TVersion = decltype(std::declval<typename TThis::TLoadContextImpl>().GetVersion()); + using TVersion = typename TTraits<TThis>::TVersion; auto SinceVersion(TVersion version) && { @@ -377,9 +485,7 @@ public: return TFieldLoadRegistrar(std::move(*this)); } - using TMissingHandler = void (*)(TThis* this_, TContext& context); - - auto WhenMissing(TMissingHandler handler) && + auto WhenMissing(TFieldMissingHandler<TThis, TContext> handler) && { MissingHandler_ = handler; return TFieldLoadRegistrar(std::move(*this)); @@ -422,7 +528,76 @@ private: TVersion MinVersion_ = static_cast<TVersion>(std::numeric_limits<int>::min()); TVersionFilter VersionFilter_ = nullptr; - TMissingHandler MissingHandler_ = nullptr; + TFieldMissingHandler<TThis, TContext> MissingHandler_ = nullptr; +}; + +template <class TThis, class TContext> +class PHOENIX_REGISTRAR_NODISCARD TVirtualFieldLoadRegistrar +{ +public: + TVirtualFieldLoadRegistrar( + TThis* this_, + TContext& context, + TStringBuf name, + TFieldLoadHandler<TThis, TContext> loadHandler) + : This_(this_) + , Context_(context) + , Name_(name) + , LoadHandler_(loadHandler) + { } + + TVirtualFieldLoadRegistrar(TVirtualFieldLoadRegistrar<TThis, TContext>&& other) + : This_(other.This_) + , Context_(other.Context_) + , Name_(other.Name_) + , LoadHandler_(other.LoadHandler) + , MinVersion_(other.MinVersion_) + , VersionFilter_(other.VersionFilter_) + , MissingHandler_(other.MissingHandler_) + { } + + using TVersion = typename TTraits<TThis>::TVersion; + + auto SinceVersion(TVersion version) && + { + MinVersion_ = version; + return TFieldLoadRegistrar(std::move(*this)); + } + + auto WhenMissing(TFieldMissingHandler<TThis, TContext> handler) && + { + MissingHandler_ = handler; + return TVirtualFieldLoadRegistrar(std::move(*this)); + } + + using TVersionFilter = bool (*)(TVersion version); + + auto InVersions(TVersionFilter filter) && + { + VersionFilter_ = filter; + return TVirtualFieldLoadRegistrar(std::move(*this)); + } + + + void operator()() && + { + if (auto version = Context_.GetVersion(); version >= MinVersion_ && (!VersionFilter_ || VersionFilter_(version))) { + Context_.Dumper().SetFieldName(Name_); + LoadHandler_(This_, Context_); + } else if (MissingHandler_) { + MissingHandler_(This_, Context_); + } + } + +private: + TThis* const This_; + TContext& Context_; + const TStringBuf Name_; + const TFieldLoadHandler<TThis, TContext> LoadHandler_; + + TVersion MinVersion_ = static_cast<TVersion>(std::numeric_limits<int>::min()); + TVersionFilter VersionFilter_ = nullptr; + TFieldMissingHandler<TThis, TContext> MissingHandler_ = nullptr; }; template <class TThis, class TContext> @@ -444,6 +619,27 @@ public: TStringBuf(name, NameLength - 1)); } + template <TFieldTag::TUnderlying TagValue, size_t NameLength> + auto VirtualField( + const char (&name)[NameLength], + TFieldLoadHandler<TThis, TContext> loadHandler) + { + return TVirtualFieldLoadRegistrar<TThis, TContext>( + This_, + Context_, + TStringBuf(name, NameLength - 1), + loadHandler); + } + + template <TFieldTag::TUnderlying TagValue, size_t NameLength> + auto VirtualField( + const char (&name)[NameLength], + TFieldLoadHandler<TThis, TContext> loadHandler, + auto&& /*saveHandler*/) + { + return VirtualField<TagValue>(name, loadHandler); + } + private: TThis* const This_; TContext& Context_; @@ -494,13 +690,10 @@ void LoadImpl(TThis* this_, TContext& context) //////////////////////////////////////////////////////////////////////////////// template <class TThis, class TContext> -using TFieldHandler = void (*)(TThis*, TContext&); - -template <class TThis, class TContext> struct TRuntimeFieldDescriptor { - TFieldHandler<TThis, TContext> LoadHandler = nullptr; - TFieldHandler<TThis, TContext> MissingHandler = nullptr; + TFieldLoadHandler<TThis, TContext> LoadHandler = nullptr; + TFieldMissingHandler<TThis, TContext> MissingHandler = nullptr; }; template <class TThis, class TContext> @@ -531,7 +724,7 @@ public: return std::move(*this); } - auto WhenMissing(TFieldHandler<TThis, TContext> handler) && + auto WhenMissing(TFieldMissingHandler<TThis, TContext> handler) && { Descriptor_->MissingHandler = handler; return std::move(*this); @@ -558,12 +751,12 @@ private: }; template <class TThis, class TContext> -class TRuntimeDeprecatedFieldDescriptorBuilderRegistar +class TRuntimeVirtualFieldDescriptorBuilderRegistar { public: using TRuntimeFieldDescriptor = NPhoenix2::NDetail::TRuntimeFieldDescriptor<TThis, TContext>; - TRuntimeDeprecatedFieldDescriptorBuilderRegistar(TRuntimeFieldDescriptor* descriptor) + TRuntimeVirtualFieldDescriptorBuilderRegistar(TRuntimeFieldDescriptor* descriptor) : Descriptor_(descriptor) { } @@ -577,7 +770,7 @@ public: return *this; } - auto WhenMissing(TFieldHandler<TThis, TContext> handler) && + auto WhenMissing(TFieldMissingHandler<TThis, TContext> handler) && { Descriptor_->MissingHandler = handler; return std::move(*this); @@ -614,11 +807,22 @@ public: } template <TFieldTag::TUnderlying TagValue> - auto DeprecatedField(auto&& /*name*/, TFieldHandler<TThis, TContext> handler) + auto VirtualField( + auto&& /*name*/, + TFieldLoadHandler<TThis, TContext> loadHandler) { auto* descriptor = AddField<TagValue>(); - descriptor->LoadHandler = handler; - return TRuntimeDeprecatedFieldDescriptorBuilderRegistar<TThis, TContext>(descriptor); + descriptor->LoadHandler = loadHandler; + return TRuntimeVirtualFieldDescriptorBuilderRegistar<TThis, TContext>(descriptor); + } + + template <TFieldTag::TUnderlying TagValue> + auto VirtualField( + auto&& name, + TFieldLoadHandler<TThis, TContext> loadHandler, + auto&& /*saveHandler*/) + { + return VirtualField<TagValue>(name, loadHandler); } auto operator()() && @@ -672,8 +876,8 @@ template <class TThis, class TContext> struct TRuntimeTypeLoadSchedule : public TRuntimeTypeLoadScheduleBase { - std::vector<TFieldHandler<TThis, TContext>> LoadFieldHandlers; - std::vector<TFieldHandler<TThis, TContext>> MissingFieldHandlers; + std::vector<TFieldLoadHandler<TThis, TContext>> LoadFieldHandlers; + std::vector<TFieldMissingHandler<TThis, TContext>> MissingFieldHandlers; }; struct TUniverseLoadState diff --git a/yt/yt/core/phoenix/unittests/phoenix_ut.cpp b/yt/yt/core/phoenix/unittests/phoenix_ut.cpp index 3dd62ff42c5..7a8eaff99b9 100644 --- a/yt/yt/core/phoenix/unittests/phoenix_ut.cpp +++ b/yt/yt/core/phoenix/unittests/phoenix_ut.cpp @@ -672,7 +672,7 @@ TEST(TPhoenixTest, NativeLoadDerivedStructNoSchema) //////////////////////////////////////////////////////////////////////////////// -namespace NDeprecatedField { +namespace NLoadOnlyVirtualField { struct S { @@ -683,45 +683,65 @@ struct S void S::RegisterMetadata(auto&& registrar) { - registrar.template DeprecatedField<1>("a", [] (TThis* this_, auto& context) { + registrar.template VirtualField<1>("a", [] (TThis* this_, auto& context) { this_->A = Load<int>(context); })(); } PHOENIX_DEFINE_TYPE(S); -} // namespace NDeprecatedField +} // namespace NLoadOnlyVirtualField -TEST(TPhoenixTest, DeprecatedField) +TEST(TPhoenixTest, LoadOnlyVirtualField) { - using namespace NDeprecatedField; + using namespace NLoadOnlyVirtualField; auto buffer = MakeBuffer([] (auto& context) { Save<int>(context, 123); }); - auto loadSchema = ConvertTo<TUniverseSchemaPtr>(TYsonString(TString(R"""( - { - types = [ - { - name = S; - tag = 1652735129u; - fields = [ - {name = a; tag = 1u}; - ]; - } - ]; - } - )"""))); - TLoadSessionGuard guard(loadSchema); - EXPECT_TRUE(NDetail::UniverseLoadState->Schedule); - auto s = Deserialize<S>(buffer); EXPECT_EQ(s.A, 123); } //////////////////////////////////////////////////////////////////////////////// +namespace NSaveLoadVirtualField { + +struct S +{ + int A = 0; + + bool operator==(const S&) const = default; + + PHOENIX_DECLARE_TYPE(S, 0x67bdf7f9); +}; + +void S::RegisterMetadata(auto&& registrar) +{ + registrar.template VirtualField<1>("a", [] (TThis* this_, auto& context) { + this_->A = Load<int>(context); + }, [] (const TThis* this_, auto& context) { + NYT::Save(context, this_->A); + })(); +} + +PHOENIX_DEFINE_TYPE(S); + +} // namespace NSaveLoadVirtualField + +TEST(TPhoenixTest, SaveLoadVirtualField) +{ + using namespace NSaveLoadVirtualField; + + S s1; + s1.A = 123; + auto s2 = Deserialize<S>(Serialize(s1)); + EXPECT_EQ(s1, s2); +} + +//////////////////////////////////////////////////////////////////////////////// + TEST(TPhoenixTest, Pair) { TPair<TString, double> p1{.First = "hello", .Second = 3.14}; |