blob: e92249a9ba181714f6d33ce88012dcb96dd42a06 [file] [log] [blame]
#pragma once
#include "errors.hpp"
#include <sdbusplus/exception.hpp>
#include <algorithm>
#include <array>
#include <stdexcept>
#include <string>
namespace utils
{
template <size_t N>
struct ConstexprString
{
constexpr ConstexprString(const char (&data)[N]) : s()
{
for (size_t i = 0; i < N; ++i)
{
s[i] = data[i];
}
}
constexpr operator std::string_view() const
{
return {s.data(), s.size()};
}
std::array<char, N> s;
};
[[noreturn]] inline void throwConversionError(std::string_view propertyName)
{
throw errors::InvalidArgument(propertyName, "Cannot convert.");
}
template <class T>
struct EnumTraits;
template <class T, T first, T last>
inline T toEnum(std::underlying_type_t<T> x)
{
if (x < static_cast<std::underlying_type_t<T>>(first) ||
x > static_cast<std::underlying_type_t<T>>(last))
{
throwConversionError(EnumTraits<T>::propertyName);
}
return static_cast<T>(x);
}
template <class T>
constexpr inline std::underlying_type_t<T> toUnderlying(T value)
{
return static_cast<std::underlying_type_t<T>>(value);
}
template <class T, size_t N>
constexpr inline T
minEnumValue(std::array<std::pair<std::string_view, T>, N> data)
{
auto min = data[0].second;
for (auto [key, value] : data)
{
if (toUnderlying(min) > toUnderlying(value))
{
min = value;
}
}
return min;
}
template <class T, size_t N>
constexpr inline T
maxEnumValue(std::array<std::pair<std::string_view, T>, N> data)
{
auto max = data[0].second;
for (auto [key, value] : data)
{
if (toUnderlying(max) < toUnderlying(value))
{
max = value;
}
}
return max;
}
template <class T, size_t N>
inline T toEnum(const std::array<std::pair<std::string_view, T>, N>& data,
const std::string& value)
{
auto it = std::find_if(
std::begin(data), std::end(data),
[&value](const auto& item) { return item.first == value; });
if (it == std::end(data))
{
throwConversionError(EnumTraits<T>::propertyName);
}
return it->second;
}
template <class T, size_t N>
inline std::string_view
enumToString(const std::array<std::pair<std::string_view, T>, N>& data,
T value)
{
auto it = std::find_if(
std::begin(data), std::end(data),
[value](const auto& item) { return item.second == value; });
if (it == std::end(data))
{
throwConversionError(EnumTraits<T>::propertyName);
}
return it->first;
}
} // namespace utils