summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbabenko <[email protected]>2024-08-15 14:13:45 +0300
committerbabenko <[email protected]>2024-08-15 14:26:08 +0300
commit1675f48e0ce19ee911fd1131b20198ad0e91fd97 (patch)
tree7e9f1c9cdb2747ce89697c029a3b2b055f368f73
parent7ed8c594b8533538dfdcc354f6b38c7c84919189 (diff)
DeprecatedField -> VirtualField; also support saving virtual fields
488c5618adaa789790af173bbb63fb9354af45a8
-rw-r--r--yt/yt/core/phoenix/descriptors.cpp6
-rw-r--r--yt/yt/core/phoenix/descriptors.h2
-rw-r--r--yt/yt/core/phoenix/load.cpp4
-rw-r--r--yt/yt/core/phoenix/schemas.cpp3
-rw-r--r--yt/yt/core/phoenix/schemas.h1
-rw-r--r--yt/yt/core/phoenix/type_decl-inl.h4
-rw-r--r--yt/yt/core/phoenix/type_def-inl.h256
-rw-r--r--yt/yt/core/phoenix/unittests/phoenix_ut.cpp62
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};