5#include <boost/pfr.hpp>
15template<
typename EnumDecl>
16 requires std::is_enum_v<typename EnumDecl::Values>
20 using E =
typename EnumDeclaration::Values;
21 auto static constexpr Keys = EnumDeclaration::Keys;
22 E static constexpr Uninitialized =
static_cast<E>(std::numeric_limits<std::underlying_type_t<E>>::max());
27 auto findRes = std::find(std::begin(
Keys), std::end(
Keys), str);
28 STORM_LOG_THROW(findRes != std::end(
Keys), storm::exceptions::WrongFormatException,
"Invalid enum value '" << str <<
"'.");
29 value =
static_cast<E>(std::distance(std::begin(
Keys), findRes));
42 return value == other;
46 auto const index =
static_cast<std::underlying_type_t<E>
>(value);
48 STORM_LOG_ASSERT(std::cmp_less(index,
Keys.size()),
"Enum value with index " << index <<
" does not have a key.");
49 return *(std::begin(
Keys) + index);
62NLOHMANN_JSON_NAMESPACE_BEGIN
70template<StormEnableSerializationConcept T>
71struct adl_serializer<T> {
72 static_assert(T::JsonKeys.size() == boost::pfr::tuple_size_v<T>,
"Number of JsonKeys does not match number of fields in struct.");
74 template<
typename JsonType>
75 static void to_json(JsonType& json, T
const& val) {
76 to_json_i<0>(json, val);
78 json =
typename JsonType::object_t();
82 template<
typename JsonType>
83 static void from_json(JsonType
const& json, T& val) {
84 STORM_LOG_THROW(json.is_object(), ::storm::exceptions::WrongFormatException,
"Expected an object, got something else.");
85 from_json_i<0>(json, val);
90 static auto get_key(std::size_t i) {
91 return std::data(T::JsonKeys)[i];
94 template<std::
size_t I,
typename JsonType>
95 static void to_json_i(JsonType& json, T
const& val) {
96 if constexpr (I < boost::pfr::tuple_size_v<T>) {
97 if constexpr (StormIsOptional<boost::pfr::tuple_element_t<I, T>>) {
98 if (boost::pfr::get<I>(val).has_value()) {
99 json[get_key(I)] = boost::pfr::get<I>(val).value();
102 json[get_key(I)] = boost::pfr::get<I>(val);
104 to_json_i<I + 1>(json, val);
108 template<std::
size_t I,
typename JsonType>
109 static void from_json_i(JsonType
const& json, T& val) {
110 if constexpr (I < boost::pfr::tuple_size_v<T>) {
111 if constexpr (StormIsOptional<boost::pfr::tuple_element_t<I, T>>) {
112 if (
json.contains(get_key(I))) {
113 boost::pfr::get<I>(val) =
json.at(get_key(I)).template get<typename boost::pfr::tuple_element_t<I, T>::value_type>();
115 boost::pfr::get<I>(val) = std::nullopt;
118 json.at(get_key(I)).get_to(boost::pfr::get<I>(val));
120 from_json_i<I + 1>(json, val);
128template<StormIsSerializedEnum T>
129struct adl_serializer<T> {
130 template<
typename JsonType>
131 static void to_json(JsonType& json, T
const& val) {
132 json = val.toString();
135 template<
typename JsonType>
137 STORM_LOG_THROW(json.is_string(), ::storm::exceptions::WrongFormatException,
"Expected a string, got something else.");
138 val = T(json.template get<std::string>());
142template<
typename... Ts>
143struct adl_serializer<
std::variant<Ts...>> {
144 template<
typename JsonType>
145 static void to_json(JsonType& json, std::variant<Ts...>
const& val) {
146 std::visit([&json](
auto const& v) { adl_serializer<std::decay_t<
decltype(v)>>
::to_json(json, v); }, val);
149 template<std::
size_t I,
typename JsonType>
150 static void from_json_i(JsonType
const& json, std::variant<Ts...>& val) {
151 static_assert(I < std::variant_size_v<std::variant<Ts...>>,
"Index out of bounds.");
152 using Ti = std::variant_alternative_t<I, std::variant<Ts...>>;
153 if constexpr (I + 1 == std::variant_size_v<std::variant<Ts...>>) {
155 val = json.template get<Ti>();
158 if (json.is_object()) {
160 if (std::all_of(json.items().begin(), json.items().end(),
161 [](
auto const& item) { return std::find(Ti::JsonKeys.begin(), Ti::JsonKeys.end(), item.key()) != Ti::JsonKeys.end(); })) {
163 val = json.template get<Ti>();
167 }
else if ((json.is_boolean() && std::is_same_v<Ti, bool>) || (json.is_string() && std::is_same_v<Ti, std::string>) ||
168 (json.is_number_integer() && std::is_integral_v<Ti>) ||
169 (json.is_number_float() && (std::is_same_v<Ti, double> || std::is_same_v<Ti, typename JsonType::number_float_t>))) {
171 val = json.template get<Ti>();
179 template<
typename JsonType>
180 static void from_json(JsonType
const& json, std::variant<Ts...>& val) {
185NLOHMANN_JSON_NAMESPACE_END
std::string_view toString() const
typename EnumDeclaration::Values E
static auto constexpr Keys
SerializedEnum(std::string_view str)
static E constexpr Uninitialized
bool operator==(E other) const
bool isInitialized() const
friend std::ostream & operator<<(std::ostream &os, SerializedEnum const &val)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
static void from_json(JsonType const &json, T &val)
static void to_json(JsonType &json, T const &val)
static void to_json(JsonType &json, std::variant< Ts... > const &val)
static void from_json_i(JsonType const &json, std::variant< Ts... > &val)
static void from_json(JsonType const &json, std::variant< Ts... > &val)
Helper struct to enable json serialization.