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