aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/yt/misc/enum.h
blob: 331eb59f1a4f2b6e31c2c91500d878d16af5abb9 (plain) (tree)
1
2
3
4
5
6
7
8
9




                                
                
                      













                                                                                
                                                                      

                          

                               


                                                         
                                                         
 
            
                                                                      





                                                                         




                                                           
                                              

                  
                                                              
 
                                         
 
                                                                                     
 



                                                  
 
                          
                                                 

                                                 
 





                                                                                                  
                                                                        
 
                                    
 
                                                           
                                                                   
 
                                                  
                                                
 
                                            




                                                                                
                                    

                                                                


                                                                         
                                

                                                                

                                                                                   
                                
                                                                       
                                                        

                                                                
                                    

                                                                
                                                                             
                                 
                                                                    
                                        
                                
                       
 

                                                                
                                    

                                                                
                                                                                       
                                 
                                                                    
                                        
                                
                       
                                                                                
   
                                    
                                                                
                                                                     

                                                                                                   
                                    

                                                                



                                                                                             
                       

                                                                                                   

                                                                                                       
                                
                                                                                                          
                                                                            
 










                                                                                             
                                                                                
                                                                 

                                      
                                                             

                                      






                                                                                
#pragma once

#include "preprocessor.h"

#include <util/generic/strbuf.h>

#include <array>
#include <optional>
#include <type_traits>
#include <vector>

#include <library/cpp/yt/exception/exception.h>

namespace NYT {

////////////////////////////////////////////////////////////////////////////////
/*
 * Smart enumerations augment C++ enum classes with a bunch of reflection
 * capabilities accessible via TEnumTraits class specialization.
 *
 * Please refer to the unit test for an actual example of usage
 * (unittests/enum_ut.cpp).
 */

// The actual overload must be provided with DEFINE_ENUM* (see below).
template <class T>
void GetEnumTraitsImpl(T);

template <class T, class S>
constexpr bool CanFitSubtype();

template <class T>
using TEnumTraitsImpl = decltype(GetEnumTraitsImpl(T()));

template <class T>
constexpr std::optional<T> TryGetEnumUnknownValueImpl(T);

template <
    class T,
    bool DomainSizeKnown = requires{ TEnumTraitsImpl<T>::DomainSize; }
>
struct TEnumTraitsWithKnownDomain
{ };

template <
    class T,
    bool = std::is_enum_v<T> && !std::is_same_v<TEnumTraitsImpl<T>, void>
>
struct TEnumTraits
{
    static constexpr bool IsEnum = false;
    static constexpr bool IsBitEnum = false;
    static constexpr bool IsStringSerializableEnum = false;
    static constexpr bool IsMonotonic = false;
};

template <class T>
struct TEnumTraitsWithKnownDomain<T, /*DomainSizeKnown*/ true>
{
    static constexpr int GetDomainSize();

    static constexpr const std::array<TStringBuf, GetDomainSize()>& GetDomainNames();
    static constexpr const std::array<T, GetDomainSize()>& GetDomainValues();

    // For non-bit enums only.
    static constexpr T GetMinValue()
        requires (!TEnumTraitsImpl<T>::IsBitEnum);
    static constexpr T GetMaxValue()
        requires (!TEnumTraitsImpl<T>::IsBitEnum);

    // For bit enums only.
    static constexpr T GetAllSetValue()
        requires (TEnumTraitsImpl<T>::IsBitEnum);
    static std::vector<T> Decompose(T value)
        requires (TEnumTraitsImpl<T>::IsBitEnum);
};

template <class T>
struct TEnumTraits<T, true>
    : public TEnumTraitsWithKnownDomain<T>
{
    static constexpr bool IsEnum = true;
    static constexpr bool IsBitEnum = TEnumTraitsImpl<T>::IsBitEnum;
    static constexpr bool IsStringSerializableEnum = TEnumTraitsImpl<T>::IsStringSerializableEnum;
    static constexpr bool IsMonotonic = TEnumTraitsImpl<T>::IsMonotonic;

    static TStringBuf GetTypeName();

    static constexpr std::optional<T> TryGetUnknownValue();
    static std::optional<TStringBuf> FindLiteralByValue(T value);
    static std::optional<T> FindValueByLiteral(TStringBuf literal);

    static constexpr bool IsKnownValue(T value)
        requires (!TEnumTraitsImpl<T>::IsBitEnum);
    static constexpr bool IsValidValue(T value);

    static TString ToString(T value);
    static T FromString(TStringBuf literal);
};

////////////////////////////////////////////////////////////////////////////////

//! Defines a smart enumeration with a specific underlying type.
/*!
 * \param enumType Enumeration type.
 * \param seq Enumeration domain encoded as a <em>sequence</em>.
 * \param underlyingType Underlying type.
 */
#define DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
    ENUM__CLASS(enumType, underlyingType, seq) \
    ENUM__BEGIN_TRAITS(enumType, underlyingType, false, false, seq) \
    ENUM__VALIDATE_UNIQUE(enumType) \
    ENUM__END_TRAITS(enumType) \
    static_assert(true)

//! Defines a smart enumeration with a specific underlying type.
//! Duplicate enumeration values are allowed.
#define DEFINE_AMBIGUOUS_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
    ENUM__CLASS(enumType, underlyingType, seq) \
    ENUM__BEGIN_TRAITS(enumType, underlyingType, false, false, seq) \
    ENUM__END_TRAITS(enumType) \
    static_assert(true)

//! Defines a smart enumeration with the default |int| underlying type.
#define DEFINE_ENUM(enumType, seq) \
    DEFINE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq)

//! Defines a smart enumeration with a specific underlying type.
/*!
 * \param enumType Enumeration type.
 * \param seq Enumeration domain encoded as a <em>sequence</em>.
 * \param underlyingType Underlying type.
 */
#define DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
    ENUM__CLASS(enumType, underlyingType, seq) \
    ENUM__BITWISE_OPS(enumType) \
    ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \
    ENUM__VALIDATE_UNIQUE(enumType) \
    ENUM__ALL_SET_VALUE(enumType, seq) \
    ENUM__END_TRAITS(enumType) \
    static_assert(true)

//! Defines a smart enumeration with a specific underlying type.
//! Duplicate enumeration values are allowed.
/*!
 * \param enumType Enumeration type.
 * \param seq Enumeration domain encoded as a <em>sequence</em>.
 * \param underlyingType Underlying type.
 */
#define DEFINE_AMBIGUOUS_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
    ENUM__CLASS(enumType, underlyingType, seq) \
    ENUM__BITWISE_OPS(enumType) \
    ENUM__BEGIN_TRAITS(enumType, underlyingType, true, false, seq) \
    ENUM__ALL_SET_VALUE(enumType, seq) \
    ENUM__END_TRAITS(enumType) \
    static_assert(true)

//! Defines a smart enumeration with the default |unsigned int| underlying type.
/*!
 * \param enumType Enumeration type.
 * \param seq Enumeration domain encoded as a <em>sequence</em>.
 */
#define DEFINE_BIT_ENUM(enumType, seq) \
    DEFINE_BIT_ENUM_WITH_UNDERLYING_TYPE(enumType, unsigned int, seq)

//! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute.
/*!
 * \param enumType Enumeration type.
 * \param seq Enumeration domain encoded as a <em>sequence</em>.
 * \param underlyingType Underlying type.
 */
#define DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
    ENUM__CLASS(enumType, underlyingType, seq) \
    ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \
    ENUM__VALIDATE_UNIQUE(enumType) \
    ENUM__END_TRAITS(enumType) \
    static_assert(true)

//! Defines a smart enumeration with a specific underlying type and IsStringSerializable attribute.
//! Duplicate enumeration values are allowed.
#define DEFINE_AMBIGUOUS_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, underlyingType, seq) \
    ENUM__CLASS(enumType, underlyingType, seq) \
    ENUM__BEGIN_TRAITS(enumType, underlyingType, false, true, seq) \
    ENUM__END_TRAITS(enumType) \
    static_assert(true)

//! Defines a smart enumeration with the default |int| underlying type and IsStringSerializable attribute.
#define DEFINE_STRING_SERIALIZABLE_ENUM(enumType, seq) \
    DEFINE_STRING_SERIALIZABLE_ENUM_WITH_UNDERLYING_TYPE(enumType, int, seq)

//! When enum from another representation (e.g. string or protobuf integer),
//! instructs the parser to treat undeclared values as |unknownValue|.
/*!
 * \param enumType Enumeration type.
 * \param unknownValue A sentinel value of #enumType.
 */
#define DEFINE_ENUM_UNKNOWN_VALUE(enumType, unknownValue) \
    [[maybe_unused]] constexpr std::optional<enumType> TryGetEnumUnknownValueImpl(enumType) \
    { \
        return enumType::unknownValue; \
    }

////////////////////////////////////////////////////////////////////////////////

//! Returns |true| iff the enumeration value is not bitwise zero.
template <typename E>
    requires TEnumTraits<E>::IsBitEnum
constexpr bool Any(E value) noexcept;

//! Returns |true| iff the enumeration value is bitwise zero.
template <typename E>
    requires TEnumTraits<E>::IsBitEnum
constexpr bool None(E value) noexcept;

////////////////////////////////////////////////////////////////////////////////

} // namespace NYT

#define ENUM_INL_H_
#include "enum-inl.h"
#undef ENUM_INL_H_