diff options
author | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2024-12-02 20:05:42 +0300 |
---|---|---|
committer | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2024-12-02 20:37:33 +0300 |
commit | c6bd6398f1bec61405c83f91872481e3b5e33510 (patch) | |
tree | fafdbaeec8430e4bcfb8d53dd273e1254001a610 | |
parent | e4293e758af131e7ef7ca74bfa1ef6f9b74b58cb (diff) | |
download | ydb-c6bd6398f1bec61405c83f91872481e3b5e33510.tar.gz |
YT-23686: Better support of UnrecognizedStrategy and DefaultUnrecognizedStrategy options
commit_hash:17934f79fcde35cab012586ea54a37681007fb70
-rw-r--r-- | yt/yt/core/ytree/unittests/yson_struct_ut.cpp | 70 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct-inl.h | 5 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct.h | 2 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct_detail-inl.h | 71 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct_detail.h | 8 |
5 files changed, 134 insertions, 22 deletions
diff --git a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp index 615fef5a32..614810de56 100644 --- a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp +++ b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp @@ -3645,5 +3645,75 @@ TEST(TYsonStructTest, OverrideWithComparisonFromTemplatedFunction) //////////////////////////////////////////////////////////////////////////////// +struct THasFieldWithDefaultedStrategy + : public TYsonStructLite +{ + TIntrusivePtr<TConfigWithOneLevelNesting> Field; + + REGISTER_YSON_STRUCT_LITE(THasFieldWithDefaultedStrategy); + + static void Register(TRegistrar registrar) + { + registrar.Parameter("field", &TThis::Field) + .Default() + .DefaultUnrecognizedStrategy(EUnrecognizedStrategy::Throw); + } +}; + +struct THasFieldWithDefaultedStrategyAndOwnRecursiveStrategy + : public TYsonStructLite +{ + TIntrusivePtr<TConfigWithOneLevelNesting> Field; + + REGISTER_YSON_STRUCT_LITE(THasFieldWithDefaultedStrategyAndOwnRecursiveStrategy); + + static void Register(TRegistrar registrar) + { + registrar.UnrecognizedStrategy(EUnrecognizedStrategy::KeepRecursive); + + registrar.Parameter("field", &TThis::Field) + .Default() + .DefaultUnrecognizedStrategy(EUnrecognizedStrategy::Throw) + .EnforceDefaultUnrecognizedStrategy(); + } +}; + +TEST(TYsonStructTest, DefaultUnrecognizedStrategy1) +{ + auto source = BuildYsonNodeFluently().BeginMap() + .Item("field").BeginMap() + .Item("unrecognized").Value(42) + .EndMap() + .EndMap(); + + THasFieldWithDefaultedStrategy yson = {}; + EXPECT_ANY_THROW(Deserialize(yson, source->AsMap())); +} + +TEST(TYsonStructTest, DefaultUnrecognizedStrategy2) +{ + auto source = BuildYsonNodeFluently().BeginMap() + .Item("field").BeginMap() + .Item("sub").BeginMap() + .EndMap() + .EndMap() + .EndMap(); + + THasFieldWithDefaultedStrategy yson = {}; + Deserialize(yson, source->AsMap()); +} + +TEST(TYsonStructTest, DefaultUnrecognizedStrategy3) +{ + auto source = BuildYsonNodeFluently().BeginMap() + .Item("field").BeginMap() + .Item("unrecognized").Value(42) + .EndMap() + .EndMap(); + + THasFieldWithDefaultedStrategyAndOwnRecursiveStrategy yson = {}; + EXPECT_ANY_THROW(Deserialize(yson, source->AsMap())); +} + } // namespace } // namespace NYT::NYTree diff --git a/yt/yt/core/ytree/yson_struct-inl.h b/yt/yt/core/ytree/yson_struct-inl.h index 6e9bdb2d96..34103976da 100644 --- a/yt/yt/core/ytree/yson_struct-inl.h +++ b/yt/yt/core/ytree/yson_struct-inl.h @@ -288,11 +288,14 @@ void Serialize(const T& value, NYson::IYsonConsumer* consumer) } template <CExternallySerializable T, CYsonStructSource TSource> -void Deserialize(T& value, TSource source, bool postprocess, bool setDefaults) +void Deserialize(T& value, TSource source, bool postprocess, bool setDefaults, std::optional<EUnrecognizedStrategy> strategy) { using TTraits = TGetExternalizedYsonStructTraits<T>; using TSerializer = typename TTraits::TExternalSerializer; auto serializer = TSerializer::template CreateWritable<T, TSerializer>(value, setDefaults); + if (strategy) { + serializer.SetUnrecognizedStrategy(*strategy); + } serializer.Load(std::move(source), postprocess, setDefaults); } diff --git a/yt/yt/core/ytree/yson_struct.h b/yt/yt/core/ytree/yson_struct.h index 4fd373e49c..24eb811a88 100644 --- a/yt/yt/core/ytree/yson_struct.h +++ b/yt/yt/core/ytree/yson_struct.h @@ -393,7 +393,7 @@ void Deserialize(TYsonStructBase& value, NYson::TYsonPullParserCursor* cursor); template <CExternallySerializable T> void Serialize(const T& value, NYson::IYsonConsumer* consumer); template <CExternallySerializable T, CYsonStructSource TSource> -void Deserialize(T& value, TSource source, bool postprocess = true, bool setDefaults = true); +void Deserialize(T& value, TSource source, bool postprocess = true, bool setDefaults = true, std::optional<EUnrecognizedStrategy> strategy = {}); template <class T> TIntrusivePtr<T> UpdateYsonStruct( diff --git a/yt/yt/core/ytree/yson_struct_detail-inl.h b/yt/yt/core/ytree/yson_struct_detail-inl.h index bc7dbdb130..3a4cdea34f 100644 --- a/yt/yt/core/ytree/yson_struct_detail-inl.h +++ b/yt/yt/core/ytree/yson_struct_detail-inl.h @@ -189,7 +189,7 @@ void LoadFromSource( std::optional<T>& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy); + std::optional<EUnrecognizedStrategy> unrecognizedStrategy); // std::vector template <CYsonStructSource TSource, CStdVector TVector> @@ -197,7 +197,7 @@ void LoadFromSource( TVector& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy); + std::optional<EUnrecognizedStrategy> unrecognizedStrategy); // any map. template <CYsonStructSource TSource, CAnyMap TMap> @@ -205,7 +205,7 @@ void LoadFromSource( TMap& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy); + std::optional<EUnrecognizedStrategy> unrecognizedStrategy); //////////////////////////////////////////////////////////////////////////////// @@ -274,14 +274,14 @@ void LoadFromSource( TIntrusivePtr<T>& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { if (!parameter) { parameter = New<T>(); } - if (recursiveUnrecognizedStrategy) { - parameter->SetUnrecognizedStrategy(*recursiveUnrecognizedStrategy); + if (unrecognizedStrategy) { + parameter->SetUnrecognizedStrategy(*unrecognizedStrategy); } parameter->Load(std::move(source), /*postprocess*/ false, /*setDefaults*/ false, path); @@ -293,9 +293,12 @@ void LoadFromSource( T& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> /*ignored*/) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { try { + if (unrecognizedStrategy) { + parameter.SetUnrecognizedStrategy(*unrecognizedStrategy); + } parameter.Load(std::move(source), /*postprocess*/ false, /*setDefaults*/ false, path); } catch (const std::exception& ex) { THROW_ERROR_EXCEPTION("Error reading parameter %v", path) @@ -309,10 +312,10 @@ void LoadFromSource( T& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> /*ignored*/) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { try { - Deserialize(parameter, std::move(source), /*postprocess*/ false, /*setDefaults*/ false); + Deserialize(parameter, std::move(source), /*postprocess*/ false, /*setDefaults*/ false, unrecognizedStrategy); } catch (const std::exception& ex) { THROW_ERROR_EXCEPTION("Error reading parameter %v", path) << ex; @@ -328,7 +331,7 @@ void LoadFromSource( TExtension& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { static_assert(CYsonStructFieldFor<TExtension, TSource>, "You must add alias TImplementsYsonStructField"); @@ -338,7 +341,7 @@ void LoadFromSource( /*postprocess*/ false, /*setDefaults*/ false, path, - recursiveUnrecognizedStrategy); + unrecognizedStrategy); } catch (const std::exception& ex) { THROW_ERROR_EXCEPTION("Error loading parameter %v", path) << ex; @@ -351,7 +354,7 @@ void LoadFromSource( std::optional<T>& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { using TTraits = TYsonSourceTraits<TSource>; @@ -363,12 +366,12 @@ void LoadFromSource( } if (parameter.has_value()) { - LoadFromSource(*parameter, std::move(source), path, recursiveUnrecognizedStrategy); + LoadFromSource(*parameter, std::move(source), path, unrecognizedStrategy); return; } T value; - LoadFromSource(value, std::move(source), path, recursiveUnrecognizedStrategy); + LoadFromSource(value, std::move(source), path, unrecognizedStrategy); parameter = std::move(value); } catch (const std::exception& ex) { @@ -383,7 +386,7 @@ void LoadFromSource( TVector& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { using TTraits = TYsonSourceTraits<TSource>; @@ -396,7 +399,7 @@ void LoadFromSource( vector.emplace_back(), elementSource, path + "/" + NYPath::ToYPathLiteral(index), - recursiveUnrecognizedStrategy); + unrecognizedStrategy); ++index; }); } catch (const std::exception& ex) { @@ -411,7 +414,7 @@ void LoadFromSource( TMap& parameter, TSource source, const NYPath::TYPath& path, - std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy) + std::optional<EUnrecognizedStrategy> unrecognizedStrategy) { using TTraits = TYsonSourceTraits<TSource>; // TODO(arkady-e1ppa): Remove "typename" when clang-14 is abolished. @@ -425,7 +428,7 @@ void LoadFromSource( value, childSource, path + "/" + NYPath::ToYPathLiteral(key), - recursiveUnrecognizedStrategy); + unrecognizedStrategy); map[DeserializeMapKey<TKey>(key)] = std::move(value); }); } catch (const std::exception& ex) { @@ -751,6 +754,13 @@ void TYsonStructParameter<TValue>::Load( const TLoadParameterOptions& options) { if (node) { + auto unrecognizedStrategy = options.RecursiveUnrecognizedRecursively; + if (EnforceDefaultUnrecognizedStrategy_) { + unrecognizedStrategy.reset(); + } + if (!unrecognizedStrategy) { + unrecognizedStrategy = DefaultUnrecognizedStrategy_; + } if (ResetOnLoad_) { NPrivate::ResetOnLoad(FieldAccessor_->GetValue(self)); } @@ -758,7 +768,7 @@ void TYsonStructParameter<TValue>::Load( FieldAccessor_->GetValue(self), std::move(node), options.Path, - options.RecursiveUnrecognizedRecursively); + unrecognizedStrategy); if (auto* bitmap = self->GetSetFieldsBitmap()) { bitmap->Set(FieldIndex_); @@ -776,6 +786,13 @@ void TYsonStructParameter<TValue>::Load( const TLoadParameterOptions& options) { if (cursor) { + auto unrecognizedStrategy = options.RecursiveUnrecognizedRecursively; + if (EnforceDefaultUnrecognizedStrategy_) { + unrecognizedStrategy.reset(); + } + if (!unrecognizedStrategy) { + unrecognizedStrategy = DefaultUnrecognizedStrategy_; + } if (ResetOnLoad_) { NPrivate::ResetOnLoad(FieldAccessor_->GetValue(self)); } @@ -783,7 +800,7 @@ void TYsonStructParameter<TValue>::Load( FieldAccessor_->GetValue(self), cursor, options.Path, - options.RecursiveUnrecognizedRecursively); + unrecognizedStrategy); if (auto* bitmap = self->GetSetFieldsBitmap()) { bitmap->Set(FieldIndex_); @@ -893,6 +910,20 @@ TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::ResetOnLoad() } template <class TValue> +TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::DefaultUnrecognizedStrategy(EUnrecognizedStrategy strategy) +{ + DefaultUnrecognizedStrategy_.emplace(strategy); + return *this; +} + +template <class TValue> +TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::EnforceDefaultUnrecognizedStrategy() +{ + EnforceDefaultUnrecognizedStrategy_ = true; + return *this; +} + +template <class TValue> const std::vector<TString>& TYsonStructParameter<TValue>::GetAliases() const { return Aliases_; diff --git a/yt/yt/core/ytree/yson_struct_detail.h b/yt/yt/core/ytree/yson_struct_detail.h index bd9f3b1917..3ed99df7ec 100644 --- a/yt/yt/core/ytree/yson_struct_detail.h +++ b/yt/yt/core/ytree/yson_struct_detail.h @@ -317,6 +317,12 @@ public: TYsonStructParameter& Alias(const TString& name); // Set field to T() (or suitable analogue) before deserializations. TYsonStructParameter& ResetOnLoad(); + // Uses given unrecognized strategy in |Load| if there was no strategy supplied. + TYsonStructParameter& DefaultUnrecognizedStrategy(EUnrecognizedStrategy strategy); + // Forces given parameter to ignore unrecognized strategy even if it set to + // some recursive version. Combination with |DefaultUnrecognizedStrategy| enables + // behavior which ensures selected default strategy for all fields below. + TYsonStructParameter& EnforceDefaultUnrecognizedStrategy(); // Register constructor with parameters as initializer of default value for ref-counted class. template <class... TArgs> @@ -333,6 +339,8 @@ private: bool TriviallyInitializedIntrusivePtr_ = false; bool Optional_ = false; bool ResetOnLoad_ = false; + std::optional<EUnrecognizedStrategy> DefaultUnrecognizedStrategy_; + bool EnforceDefaultUnrecognizedStrategy_ = false; const int FieldIndex_ = -1; }; |