$darkmode
enum.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
23 #pragma once
24 
25 #include <map> // for map<>
26 #include <string> // for string
27 #include <type_traits> // for enable_if_t<>, is_enum<>
28 #include <utility> // for make_pair, move
29 
30 #include <fable/fable_fwd.hpp>
31 #include <fable/json.hpp>
32 
51 #define ENUM_SERIALIZATION(xType, xMap) \
52  inline const std::map<xType, std::string>& enum_serialization(xType) { \
53  static std::map<xType, std::string> data xMap; \
54  return data; \
55  } \
56  inline const std::map<std::string, xType>& enum_deserialization(xType) { \
57  static const std::map<std::string, xType> data = ::fable::invert(enum_serialization(xType())); \
58  return data; \
59  } \
60  inline void to_json(::fable::Json& j, const xType& v) { j = enum_serialization(v).at(v); } \
61  inline void from_json(const ::fable::Json& j, xType& v) { \
62  v = enum_deserialization(v).at(j.get<std::string>()); \
63  }
64 
65 #define FABLE_ENUM_SERIALIZATION(xType, xMap) \
66  namespace fable { \
67  template <> \
68  struct EnumSerializer<xType> { \
69  static const std::map<xType, std::string>& serialization() { \
70  static const std::map<xType, std::string> ser xMap; \
71  return ser; \
72  } \
73  static const std::map<std::string, xType>& deserialization() { \
74  static std::map<std::string, xType> de = \
75  ::fable::invert(EnumSerializer<xType>::serialization()); \
76  return de; \
77  } \
78  }; \
79  } \
80  namespace nlohmann { \
81  template <> \
82  struct adl_serializer<xType> { \
83  static void to_json(json& j, const xType& e) { j = ::fable::to_string(e); } \
84  static void from_json(const json& j, xType& e) { \
85  e = ::fable::from_string<xType>(j.get<std::string>()); \
86  } \
87  }; \
88  }
89 
90 namespace fable {
91 
100 template <typename X, typename Y>
101 std::map<Y, X> invert(const std::map<X, Y>& m) {
102  std::map<Y, X> m_prime;
103  for (const auto& kv : m) {
104  m_prime.insert(std::make_pair(kv.second, kv.first));
105  }
106  return m_prime;
107 }
108 
109 template <typename T>
111  // Implement:
112  // static const std::map<T, std::string>& serialization();
113 
114  // Implement:
115  // static const std::map<std::string, T>& deserialization();
116 };
117 
118 template <typename T>
120  using one = char;
121  using two = struct { char x[2]; };
122 
123  template <typename C>
124  static one test(decltype(&::fable::EnumSerializer<C>::serialization));
125  template <typename C>
126  static two test(...);
127 
128  public:
129  enum { value = sizeof(test<T>(0)) == sizeof(one) };
130 };
131 
132 template <typename T>
133 inline constexpr bool has_enum_serializer_v = has_enum_serializer<T>::value;
134 
135 template <typename T, bool EnumSerializerPresent>
137 
138 template <typename T>
139 struct EnumSerializerImpl<T, true> {
140  static const std::map<T, std::string>& serialization_impl() {
142  }
143  static const std::map<std::string, T>& deserialization_impl() {
145  }
146 };
147 
148 template <typename T>
149 struct EnumSerializerImpl<T, false> {
150  static const std::map<T, std::string>& serialization_impl() { return enum_serialization(T()); }
151  static const std::map<std::string, T>& deserialization_impl() {
152  return enum_deserialization(T());
153  }
154 };
155 
156 template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
157 const std::map<T, std::string>& enum_serialization() {
158  return EnumSerializerImpl<T, has_enum_serializer_v<T>>::serialization_impl();
159 }
160 
161 template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
162 const std::map<std::string, T>& enum_deserialization() {
163  return EnumSerializerImpl<T, has_enum_serializer_v<T>>::deserialization_impl();
164 }
165 
166 template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
167 std::string to_string(T x) {
168  return enum_serialization<T>().at(x);
169 }
170 
171 template <typename T, std::enable_if_t<std::is_enum_v<T>, int> = 0>
172 T from_string(const std::string& s) {
173  return enum_deserialization<T>().at(s);
174 }
175 
176 } // namespace fable
Definition: enum.hpp:119
std::map< Y, X > invert(const std::map< X, Y > &m)
Definition: enum.hpp:101
Definition: enum.hpp:136
Definition: enum.hpp:110