diff options
author | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2023-12-05 14:44:02 +0300 |
---|---|---|
committer | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2023-12-05 15:47:34 +0300 |
commit | d7830d26621b08d508ba92fccf9e4971cc8ded61 (patch) | |
tree | 231e17a9b97711289a1eb59a7fad4e140e26c515 | |
parent | 496b43dd6e141cae303b3a4c727cabc0d04ed1ae (diff) | |
download | ydb-d7830d26621b08d508ba92fccf9e4971cc8ded61.tar.gz |
YT-20547: OperationId is strongly typed
-rw-r--r-- | library/cpp/yt/misc/strong_typedef-inl.h | 32 | ||||
-rw-r--r-- | library/cpp/yt/misc/strong_typedef.h | 12 | ||||
-rw-r--r-- | library/cpp/yt/misc/wrapper_traits-inl.h | 109 | ||||
-rw-r--r-- | library/cpp/yt/misc/wrapper_traits.h | 73 | ||||
-rw-r--r-- | ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp | 2 | ||||
-rw-r--r-- | yt/yt/client/driver/scheduler_commands.h | 5 | ||||
-rw-r--r-- | yt/yt/client/job_tracker_client/public.h | 3 | ||||
-rw-r--r-- | yt/yt/client/object_client/public.h | 3 | ||||
-rw-r--r-- | yt/yt/client/scheduler/operation_id_or_alias.cpp | 2 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_serializable-inl.h | 5 | ||||
-rw-r--r-- | yt/yt/core/ytree/yson_struct_detail-inl.h | 6 |
11 files changed, 235 insertions, 17 deletions
diff --git a/library/cpp/yt/misc/strong_typedef-inl.h b/library/cpp/yt/misc/strong_typedef-inl.h index 00f0cc0cc8..d24c76c1dd 100644 --- a/library/cpp/yt/misc/strong_typedef-inl.h +++ b/library/cpp/yt/misc/strong_typedef-inl.h @@ -4,6 +4,8 @@ #include "strong_typedef.h" #endif +#include "wrapper_traits.h" + #include <util/generic/strbuf.h> #include <functional> @@ -62,7 +64,8 @@ constexpr T&& TStrongTypedef<T, TTag>::Underlying() && template <class T, class TTag> constexpr bool TStrongTypedef<T, TTag>::operator==(const TStrongTypedef& rhs) const - noexcept(std::same_as<T, void> || noexcept(Underlying_ == rhs.Underlying_)) + noexcept(noexcept(Underlying_ == rhs.Underlying_)) + requires std::equality_comparable<T> { //! NB: We add a constexpr branch to keep constexprness of the function //! without making extra specializations explicitly. @@ -75,7 +78,8 @@ constexpr bool TStrongTypedef<T, TTag>::operator==(const TStrongTypedef& rhs) co template <class T, class TTag> constexpr auto TStrongTypedef<T, TTag>::operator<=>(const TStrongTypedef& rhs) const - noexcept(std::same_as<T, void> || noexcept(Underlying_ <=> rhs.Underlying_)) + noexcept(noexcept(Underlying_ <=> rhs.Underlying_)) + requires std::three_way_comparable<T> { //! NB: We add a constexpr branch to keep constexprness of the function //! without making extra specializations explicitly. @@ -111,7 +115,7 @@ struct TStrongTypedefTraits<TStrongTypedef<T, TTag>> //////////////////////////////////////////////////////////////////////////////// template <class T, class TChar> - requires TStrongTypedefTraits<T>::IsStrongTypedef + requires CStrongTypedef<T> bool TryFromStringImpl(const TChar* data, size_t size, T& value) { return TryFromString(data, size, value.Underlying()); @@ -130,6 +134,28 @@ void FormatValue(TStringBuilderBase* builder, const TStrongTypedef<T, TTag>& val //////////////////////////////////////////////////////////////////////////////// +template <class T, class TTag> +struct TBasicWrapperTraits<TStrongTypedef<T, TTag>> +{ + static constexpr bool IsTrivialWrapper = false; + + using TUnwrapped = T; + + static constexpr bool HasValue(const TStrongTypedef<T, TTag>&) noexcept + { + return true; + } + + template <class U> + requires std::same_as<std::remove_cvref_t<U>, TStrongTypedef<T, TTag>> + static constexpr decltype(auto) Unwrap(U&& wrapper) noexcept + { + return std::forward<U>(wrapper).Underlying(); + } +}; + +//////////////////////////////////////////////////////////////////////////////// + } // namespace NYT namespace std { diff --git a/library/cpp/yt/misc/strong_typedef.h b/library/cpp/yt/misc/strong_typedef.h index 8ed0810b53..3b093026a4 100644 --- a/library/cpp/yt/misc/strong_typedef.h +++ b/library/cpp/yt/misc/strong_typedef.h @@ -33,10 +33,12 @@ public: constexpr explicit operator T&(); constexpr bool operator==(const TStrongTypedef& rhs) const - noexcept(std::same_as<T, void> || noexcept(Underlying_ == rhs.Underlying_)); + noexcept(noexcept(Underlying_ == rhs.Underlying_)) + requires std::equality_comparable<T>; constexpr auto operator<=>(const TStrongTypedef& rhs) const - noexcept(std::same_as<T, void> || noexcept(Underlying_ <=> rhs.Underlying_)); + noexcept(noexcept(Underlying_ <=> rhs.Underlying_)) + requires std::three_way_comparable<T>; explicit operator bool() const noexcept(noexcept(static_cast<bool>(Underlying_))); @@ -61,6 +63,12 @@ private: { }; \ using T = ::NYT::TStrongTypedef<TUnderlying, T##Tag>; \ +template <class T> +struct TStrongTypedefTraits; + +template <class T> +concept CStrongTypedef = TStrongTypedefTraits<T>::IsStrongTypedef; + //////////////////////////////////////////////////////////////////////////////// } // namespace NYT diff --git a/library/cpp/yt/misc/wrapper_traits-inl.h b/library/cpp/yt/misc/wrapper_traits-inl.h new file mode 100644 index 0000000000..88d1af5945 --- /dev/null +++ b/library/cpp/yt/misc/wrapper_traits-inl.h @@ -0,0 +1,109 @@ +#ifndef WRAPPER_TRAITS_INL_H_ +#error "Direct inclusion of this file is not allowed, include wrapper_traits.h" +// For the sake of sane code completion. +#include "wrapper_traits.h" +#endif + +#include <library/cpp/yt/assert/assert.h> + +#include <optional> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> + requires std::is_object_v<T> +template <class U> + requires std::same_as<std::remove_cvref_t<U>, T> +constexpr decltype(auto) TBasicWrapperTraits<T>::Unwrap(U&& wrapper) noexcept +{ + return std::forward<U>(wrapper); +} + +template <class T> + requires std::is_object_v<T> +constexpr bool TBasicWrapperTraits<T>::HasValue(const T&) noexcept +{ + return true; +} + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> + requires std::is_object_v<T> +template <class U> + requires std::same_as<std::remove_cvref_t<U>, T> +constexpr decltype(auto) TWrapperTraits<T>::Unwrap(U&& wrapper) +{ + YT_VERIFY(HasValue(wrapper)); + return TBasicWrapperTraits<T>::Unwrap(std::forward<U>(wrapper)); +} + +template <class T> + requires std::is_object_v<T> +template <class U> + requires std::same_as<std::remove_cvref_t<U>, T> +constexpr decltype(auto) TWrapperTraits<T>::RecursiveUnwrap(U&& wrapper) +{ + using TDecayedU = std::remove_cvref_t<U>; + using TTraits = TWrapperTraits<TDecayedU>; + using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>; + + if constexpr (CNonTrivialWrapper<TDecayedU>) { + return TInnerTraits::RecursiveUnwrap(TTraits::Unwrap(std::forward<U>(wrapper))); + } else { + return TTraits::Unwrap(std::forward<U>(wrapper)); + } +} + +template <class T> + requires std::is_object_v<T> +constexpr bool TWrapperTraits<T>::HasValue(const T& wrapper) noexcept +{ + return TBasicWrapperTraits<T>::HasValue(wrapper); +} + +template <class T> + requires std::is_object_v<T> +constexpr bool TWrapperTraits<T>::RecursiveHasValue(const T& wrapper) noexcept +{ + using TTraits = TWrapperTraits<T>; + using TInnerTraits = TWrapperTraits<typename TTraits::TUnwrapped>; + + if constexpr (CNonTrivialWrapper<T>) { + return TTraits::HasValue(wrapper) && TInnerTraits::HasValue(TTraits::Unwrap(wrapper)); + } else { + return TTraits::HasValue(wrapper); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +//! Some standard library specializations + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +struct TBasicWrapperTraits<std::optional<T>> +{ + static constexpr bool IsTrivialWrapper = false; + + using TUnwrapped = T; + + static constexpr bool HasValue(const std::optional<T>& optional) noexcept + { + return optional.has_value(); + } + + template <class U> + requires std::same_as<std::remove_cvref_t<U>, std::optional<T>> + static decltype(auto) Unwrap(U&& optional) + { + return *std::forward<U>(optional); + } +}; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT diff --git a/library/cpp/yt/misc/wrapper_traits.h b/library/cpp/yt/misc/wrapper_traits.h new file mode 100644 index 0000000000..61a97b8ea4 --- /dev/null +++ b/library/cpp/yt/misc/wrapper_traits.h @@ -0,0 +1,73 @@ +#pragma once + +#include <utility> + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +//! Default implementation of wrapper traits you can specialize for your type +template <class T> + requires std::is_object_v<T> +struct TBasicWrapperTraits +{ + static constexpr bool IsTrivialWrapper = true; + + using TUnwrapped = T; + + //! Default implementations just forward the argument + template <class U> + requires std::same_as<std::remove_cvref_t<U>, T> + static constexpr decltype(auto) Unwrap(U&& wrapper) noexcept; + + static constexpr bool HasValue(const T& wrapper) noexcept; +}; + +//////////////////////////////////////////////////////////////////////////////// + +//! Represents common denominator of every single value wrapper +template <class T> + requires std::is_object_v<T> +struct TWrapperTraits +{ +public: + static constexpr bool IsTrivialWrapper = TBasicWrapperTraits<T>::IsTrivialWrapper; + + using TWrapped = T; + using TUnwrapped = typename TBasicWrapperTraits<T>::TUnwrapped; + + static constexpr bool HasValue(const T& wrapper) noexcept; + + static constexpr bool RecursiveHasValue(const T& wrapper) noexcept; + + template <class U> + requires std::same_as<std::remove_cvref_t<U>, T> + static constexpr decltype(auto) Unwrap(U&& wrapper); + + template <class U> + requires std::same_as<std::remove_cvref_t<U>, T> + static constexpr decltype(auto) RecursiveUnwrap(U&& wrapper); + + using TRecursiveUnwrapped = std::remove_cvref_t<decltype(TWrapperTraits<T>::RecursiveUnwrap(std::declval<T>()))>; +}; + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +concept CNonTrivialWrapper = + (!TBasicWrapperTraits<T>::IsTrivialWrapper) && + requires (T& wrapper, const T& const_wrapper) { + typename TBasicWrapperTraits<T>::TUnwrapped; + { TBasicWrapperTraits<T>::Unwrap(wrapper) } -> std::same_as<typename TBasicWrapperTraits<T>::TUnwrapped&>; + { TBasicWrapperTraits<T>::Unwrap(std::move(wrapper)) } -> std::same_as<typename TBasicWrapperTraits<T>::TUnwrapped&&>; + { TBasicWrapperTraits<T>::Unwrap(const_wrapper) } -> std::same_as<const typename TBasicWrapperTraits<T>::TUnwrapped&>; + { TBasicWrapperTraits<T>::HasValue(const_wrapper) } -> std::same_as<bool>; + }; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT + +#define WRAPPER_TRAITS_INL_H_ +#include "wrapper_traits-inl.h" +#undef WRAPPER_TRAITS_INL_H_ diff --git a/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp b/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp index d8a7a70a39..37e401aa90 100644 --- a/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp +++ b/ydb/library/yql/providers/dq/actors/yt/yt_resource_manager.cpp @@ -58,7 +58,7 @@ namespace NYql { , ClusterName(clusterName) , YtWrapper(ytWrapper) , ParentId(parentId) - , OperationId(NYT::NScheduler::TOperationId::FromString(operationId)) + , OperationId(NYT::NScheduler::TOperationId(NYT::TGuid::FromString(operationId))) , MutationId(mutationId) , Counters(counters) { } diff --git a/yt/yt/client/driver/scheduler_commands.h b/yt/yt/client/driver/scheduler_commands.h index 28f68fd757..b0daea15fb 100644 --- a/yt/yt/client/driver/scheduler_commands.h +++ b/yt/yt/client/driver/scheduler_commands.h @@ -35,8 +35,9 @@ public: .Default(); registrar.Postprocessor([] (TThis* command) { - if (!command->OperationId.IsEmpty() && command->OperationAlias.operator bool() || - command->OperationId.IsEmpty() && !command->OperationAlias.operator bool()) + auto operationId = command->OperationId; + if (operationId && command->OperationAlias.has_value() || + !operationId && !command->OperationAlias.has_value()) { THROW_ERROR_EXCEPTION("Exactly one of \"operation_id\" and \"operation_alias\" should be set") << TErrorAttribute("operation_id", command->OperationId) diff --git a/yt/yt/client/job_tracker_client/public.h b/yt/yt/client/job_tracker_client/public.h index 984fa0fcec..5e1886f458 100644 --- a/yt/yt/client/job_tracker_client/public.h +++ b/yt/yt/client/job_tracker_client/public.h @@ -12,7 +12,8 @@ YT_DEFINE_STRONG_TYPEDEF(TJobId, TGuid); extern const TJobId NullJobId; -using TOperationId = TGuid; +YT_DEFINE_STRONG_TYPEDEF(TOperationId, TGuid); + extern const TOperationId NullOperationId; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/client/object_client/public.h b/yt/yt/client/object_client/public.h index d8f98323f6..1d002cdc36 100644 --- a/yt/yt/client/object_client/public.h +++ b/yt/yt/client/object_client/public.h @@ -5,6 +5,7 @@ #include <library/cpp/yt/misc/hash.h> #include <yt/yt/client/election/public.h> +#include <yt/yt/client/job_tracker_client/public.h> #include <library/cpp/yt/misc/strong_typedef.h> @@ -345,7 +346,7 @@ constexpr EObjectType MaxErasureJournalChunkPartType = EObjectType::ErasureJourn using TTransactionId = TObjectId; constexpr TTransactionId NullTransactionId = {}; -using TOperationId = TObjectId; +using NJobTrackerClient::TOperationId; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/client/scheduler/operation_id_or_alias.cpp b/yt/yt/client/scheduler/operation_id_or_alias.cpp index 4a64364815..5711c11c69 100644 --- a/yt/yt/client/scheduler/operation_id_or_alias.cpp +++ b/yt/yt/client/scheduler/operation_id_or_alias.cpp @@ -24,7 +24,7 @@ TOperationIdOrAlias TOperationIdOrAlias::FromString(TString operationIdOrAlias) if (!operationIdOrAlias.empty() && operationIdOrAlias[0] == '*') { return TOperationIdOrAlias(operationIdOrAlias); } else { - return TOperationIdOrAlias(TOperationId::FromString(operationIdOrAlias)); + return TOperationIdOrAlias(TOperationId(TGuid::FromString(operationIdOrAlias))); } } diff --git a/yt/yt/core/ytree/yson_serializable-inl.h b/yt/yt/core/ytree/yson_serializable-inl.h index 7269174a30..b28578fd39 100644 --- a/yt/yt/core/ytree/yson_serializable-inl.h +++ b/yt/yt/core/ytree/yson_serializable-inl.h @@ -21,6 +21,7 @@ #include <yt/yt/core/actions/bind.h> #include <library/cpp/yt/misc/enum.h> +#include <library/cpp/yt/misc/wrapper_traits.h> #include <util/datetime/base.h> @@ -622,9 +623,7 @@ concept SupportsDontSerializeDefaultImpl = template <class T> concept SupportsDontSerializeDefault = - SupportsDontSerializeDefaultImpl<T> || - TStdOptionalTraits<T>::IsStdOptional && - SupportsDontSerializeDefaultImpl<typename TStdOptionalTraits<T>::TValueType>; + SupportsDontSerializeDefaultImpl<typename TWrapperTraits<T>::TRecursiveUnwrapped>; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/ytree/yson_struct_detail-inl.h b/yt/yt/core/ytree/yson_struct_detail-inl.h index ce7ded1def..bee8d63aeb 100644 --- a/yt/yt/core/ytree/yson_struct_detail-inl.h +++ b/yt/yt/core/ytree/yson_struct_detail-inl.h @@ -9,6 +9,8 @@ #include <yt/yt/core/yson/token_writer.h> +#include <library/cpp/yt/misc/wrapper_traits.h> + namespace NYT::NYTree { //////////////////////////////////////////////////////////////////////////////// @@ -31,9 +33,7 @@ concept SupportsDontSerializeDefaultImpl = template <class T> concept SupportsDontSerializeDefault = - SupportsDontSerializeDefaultImpl<T> || - TStdOptionalTraits<T>::IsStdOptional && - SupportsDontSerializeDefaultImpl<typename TStdOptionalTraits<T>::TValueType>; + SupportsDontSerializeDefaultImpl<typename TWrapperTraits<T>::TRecursiveUnwrapped>; //////////////////////////////////////////////////////////////////////////////// |