#pragma once #include #include #include #include #include namespace NYT { //////////////////////////////////////////////////////////////////////////////// class TErrorCodeRegistry { public: static TErrorCodeRegistry* Get(); struct TErrorCodeInfo { TString Namespace; //! Human-readable error code name. TString Name; bool operator==(const TErrorCodeInfo& rhs) const; }; struct TErrorCodeRangeInfo { int From; int To; TString Namespace; std::function Formatter; TErrorCodeInfo Get(int code) const; bool Intersects(const TErrorCodeRangeInfo& other) const; bool Contains(int value) const; }; //! Retrieves info from registered codes and code ranges. TErrorCodeInfo Get(int code) const; //! Retrieves information about registered codes. THashMap GetAllErrorCodes() const; //! Retrieves information about registered code ranges. std::vector GetAllErrorCodeRanges() const; //! Registers a single error code. void RegisterErrorCode(int code, const TErrorCodeInfo& errorCodeInfo); //! Registers a range of error codes given a human-readable code to name formatter. void RegisterErrorCodeRange(int from, int to, TString namespaceName, std::function formatter); static TString ParseNamespace(const std::type_info& errorCodeEnumTypeInfo); private: THashMap CodeToInfo_; std::vector ErrorCodeRanges_; void CheckCodesAgainstRanges() const; }; void FormatValue( TStringBuilderBase* builder, const TErrorCodeRegistry::TErrorCodeInfo& errorCodeInfo, TStringBuf spec); void FormatValue( TStringBuilderBase* builder, const TErrorCodeRegistry::TErrorCodeRangeInfo& errorCodeInfo, TStringBuf spec); //////////////////////////////////////////////////////////////////////////////// #define YT_DEFINE_ERROR_ENUM(seq) \ DEFINE_ENUM(EErrorCode, seq); \ YT_ATTRIBUTE_USED inline const void* ErrorEnum_EErrorCode = [] { \ for (auto errorCode : ::NYT::TEnumTraits::GetDomainValues()) { \ ::NYT::TErrorCodeRegistry::Get()->RegisterErrorCode( \ static_cast(errorCode), \ {::NYT::TErrorCodeRegistry::ParseNamespace(typeid(EErrorCode)), ToString(errorCode)}); \ } \ return nullptr; \ } () //////////////////////////////////////////////////////////////////////////////// //! NB: This macro should only by used in cpp files. #define YT_DEFINE_ERROR_CODE_RANGE(from, to, namespaceName, formatter) \ YT_STATIC_INITIALIZER( \ ::NYT::TErrorCodeRegistry::Get()->RegisterErrorCodeRange( \ from, \ to, \ namespaceName, \ formatter)); //////////////////////////////////////////////////////////////////////////////// } // namespace NYT