1 #pragma once 2 3 #include <sdbusplus/exception.hpp> 4 5 #include <algorithm> 6 #include <array> 7 #include <stdexcept> 8 #include <string> 9 10 namespace utils 11 { 12 13 template <class T> 14 struct EnumTraits 15 { 16 [[noreturn]] static void throwConversionError() 17 { 18 throw sdbusplus::exception::SdBusError( 19 static_cast<int>(std::errc::invalid_argument), 20 "Invalid enum value"); 21 } 22 }; 23 24 template <class T, T first, T last> 25 inline T toEnum(std::underlying_type_t<T> x) 26 { 27 if (x < static_cast<std::underlying_type_t<T>>(first) || 28 x > static_cast<std::underlying_type_t<T>>(last)) 29 { 30 EnumTraits<T>::throwConversionError(); 31 } 32 return static_cast<T>(x); 33 } 34 35 template <class T> 36 constexpr inline std::underlying_type_t<T> toUnderlying(T value) 37 { 38 return static_cast<std::underlying_type_t<T>>(value); 39 } 40 41 template <class T, size_t N> 42 constexpr inline T 43 minEnumValue(std::array<std::pair<std::string_view, T>, N> data) 44 { 45 auto min = data[0].second; 46 for (auto [key, value] : data) 47 { 48 if (toUnderlying(min) > toUnderlying(value)) 49 { 50 min = value; 51 } 52 } 53 return min; 54 } 55 56 template <class T, size_t N> 57 constexpr inline T 58 maxEnumValue(std::array<std::pair<std::string_view, T>, N> data) 59 { 60 auto max = data[0].second; 61 for (auto [key, value] : data) 62 { 63 if (toUnderlying(max) < toUnderlying(value)) 64 { 65 max = value; 66 } 67 } 68 return max; 69 } 70 71 template <class T, size_t N> 72 inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data, 73 const std::string& value) 74 { 75 auto it = std::find_if( 76 std::begin(data), std::end(data), 77 [&value](const auto& item) { return item.first == value; }); 78 if (it == std::end(data)) 79 { 80 EnumTraits<T>::throwConversionError(); 81 } 82 return it->second; 83 } 84 85 template <class T, size_t N> 86 inline std::string_view 87 enumToString(const std::array<std::pair<std::string_view, T>, N>& data, 88 T value) 89 { 90 auto it = std::find_if( 91 std::begin(data), std::end(data), 92 [value](const auto& item) { return item.second == value; }); 93 if (it == std::end(data)) 94 { 95 EnumTraits<T>::throwConversionError(); 96 } 97 return it->first; 98 } 99 100 } // namespace utils 101