xref: /openbmc/telemetry/src/utils/conversion.hpp (revision b8cc78dd)
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