encoding.h
Go to the documentation of this file.
1 #ifndef GARLIC_ENCODING_H
2 #define GARLIC_ENCODING_H
3 
8 #include "layer.h"
9 #include "containers.h"
10 
11 namespace garlic {
12 
13  template<typename Type>
14  struct coder {};
15 
16  template<>
17  struct coder<int> {
18 
19  template<GARLIC_VIEW Layer>
20  static inline int
21  decode(Layer&& layer) { return layer.get_int(); }
22 
23  template<GARLIC_REF Layer>
24  static inline void
25  encode(Layer&& layer, int value) { layer.set_int(value); }
26 
27  template<GARLIC_VIEW Layer, typename Callable>
28  static inline void
29  safe_decode(Layer&& layer, Callable&& cb) {
30  if (layer.is_int())
31  cb(layer.get_int());
32  }
33  };
34 
35  template<>
36  struct coder<bool> {
37 
38  template<GARLIC_VIEW Layer>
39  static inline bool
40  decode(Layer&& layer) { return layer.get_bool(); }
41 
42  template<GARLIC_REF Layer>
43  static inline void
44  encode(Layer&& layer, bool value) { layer.set_bool(value); }
45 
46  template<GARLIC_VIEW Layer, typename Callable>
47  static inline void
48  safe_decode(Layer&& layer, Callable&& cb) {
49  if (layer.is_bool())
50  cb(layer.get_bool());
51  }
52  };
53 
54  template<>
55  struct coder<std::string> {
56 
57  template<GARLIC_VIEW Layer>
58  static inline std::string
59  decode(Layer&& layer) { return layer.get_string(); }
60 
61  template<GARLIC_REF Layer>
62  static inline void
63  encode(Layer&& layer, const std::string& value) {
64  layer.set_string(value.c_str());
65  }
66 
67  template<GARLIC_VIEW Layer, typename Callable>
68  static inline void
69  safe_decode(Layer&& layer, Callable&& cb) {
70  if (layer.is_string())
71  cb(layer.get_string());
72  }
73  };
74 
75  template<>
76  struct coder<std::string_view> {
77 
78  template<GARLIC_VIEW Layer>
79  static inline std::string_view
80  decode(Layer&& layer) { return layer.get_string_view(); }
81 
82  template<GARLIC_REF Layer>
83  static inline void
84  encode(Layer&& layer, std::string_view value) {
85  layer.set_string(value.data());
86  }
87 
88  template<GARLIC_VIEW Layer, typename Callable>
89  static inline void
90  safe_decode(Layer&& layer, Callable&& cb) {
91  if (layer.is_string())
92  cb(layer.get_string_view());
93  }
94  };
95 
96  template<>
97  struct coder<text> {
98 
99  template<GARLIC_VIEW Layer>
100  static inline text
101  decode(Layer&& layer) {
102  auto view = layer.get_string_view();
103  return text(view.data(), view.size());
104  }
105 
106  template<GARLIC_REF Layer>
107  static inline void
108  encode(Layer&& layer, text value) {
109  layer.set_string(value.data());
110  }
111 
112  template<GARLIC_VIEW Layer, typename Callable>
113  static inline void
114  safe_decode(Layer&& layer, Callable&& cb) {
115  if (layer.is_string())
116  cb(coder::decode(layer));
117  }
118  };
119 
120  template<>
121  struct coder<const char*> {
122 
123  template<GARLIC_VIEW Layer>
124  static inline const char*
125  decode(Layer&& layer) { return layer.get_cstr(); }
126 
127  template<GARLIC_REF Layer>
128  static inline void
129  encode(Layer&& layer, const char* value) { layer.set_string(value); }
130 
131  template<GARLIC_VIEW Layer, typename Callable>
132  static inline void
133  safe_decode(Layer&& layer, Callable&& cb) {
134  if (layer.is_string())
135  cb(layer.get_cstr());
136  }
137  };
138 
139  template<>
140  struct coder<double> {
141 
142  template<GARLIC_VIEW Layer>
143  static inline double
144  decode(Layer&& layer) { return layer.get_double(); }
145 
146  template<GARLIC_REF Layer>
147  static inline void
148  encode(Layer&& layer, double value) {
149  layer.set_double(value);
150  }
151 
152  template<GARLIC_VIEW Layer, typename Callable>
153  static inline void
154  safe_decode(Layer&& layer, Callable&& cb) {
155  if (layer.is_double())
156  cb(layer.get_double());
157  }
158  };
159 
160  namespace internal {
161 
162  template<typename, typename, class = void>
163  struct has_explicit_decoder : std::false_type {};
164 
165  template<typename Type, typename Layer>
166  struct has_explicit_decoder<
167  Type, Layer,
168  std::void_t<decltype(coder<Type>::decode(std::declval<Layer>()))>> : std::true_type {};
169 
170  template<typename T, typename L>
171  using explicit_safe_decode_t = decltype(
172  coder<T>::safe_decode(std::declval<L>(), std::declval<void(*)(T&&)>()));
173 
174  template<typename, typename, class = void>
175  struct has_explicit_safe_decoder : std::false_type {};
176 
177  template<typename, typename, class = void>
178  struct has_explicit_encoder : std::false_type {};
179 
180  template<typename Type, typename Layer>
181  struct has_explicit_encoder<
182  Type, Layer,
183  std::void_t<
184  decltype(coder<Type>::encode(std::declval<Layer>(), std::declval<const Type&>()))
185  >> : std::true_type {};
186 
187  template<typename Type, typename Layer>
188  struct has_explicit_safe_decoder<
189  Type, Layer,
190  std::void_t<internal::explicit_safe_decode_t<Type, Layer>>> : std::true_type {};
191 
192  template<typename, typename, class = void>
193  struct is_layer_constructible : std::false_type{};
194 
195  template<typename Type, typename Layer>
196  struct is_layer_constructible<
197  Type, Layer,
198  std::void_t<decltype(Type(std::declval<Layer>()))>> : std::true_type {};
199 
200  template<typename, typename, class = void>
201  struct has_decode_layer_method : std::false_type {};
202 
203  template<typename Type, typename Layer>
204  struct has_decode_layer_method<
205  Type, Layer,
206  std::void_t<decltype(Type::decode(std::declval<Layer>()))>> : std::true_type {};
207 
208  template<typename, typename, class = void>
209  struct has_encode_layer_method : std::false_type {};
210 
211  template<typename Type, typename Layer>
212  struct has_encode_layer_method<
213  Type, Layer,
214  std::void_t<
215  decltype(Type::encode(std::declval<Layer>(), std::declval<const Type&>()))
216  >> : std::true_type {};
217 
218  template<typename, typename, class = void>
219  struct has_safe_decode_layer_method : std::false_type {};
220 
221  template<typename Type, typename Layer>
222  struct has_safe_decode_layer_method<
223  Type, Layer,
224  std::void_t<
225  decltype(Type::safe_decode(std::declval<Layer>(), std::declval<void(*)(Type&&)>()))>
226  > : std::true_type {};
227 
228  template<typename Type, typename Layer>
229  constexpr bool use_explicit_decoder = has_explicit_decoder<Type, Layer>::value;
230 
231  template<typename Type, typename Layer>
232  constexpr bool use_explicit_safe_decoder = has_explicit_safe_decoder<Type, Layer>::value;
233 
234  template<typename Type, typename Layer>
235  constexpr bool use_decode_layer_method =
236  has_decode_layer_method<Type, Layer>::value
237  && !has_explicit_decoder<Type, Layer>::value;
238 
239  template<typename Type, typename Layer>
240  constexpr bool use_safe_decode_layer_method =
241  has_safe_decode_layer_method<Type, Layer>::value
242  && !has_explicit_safe_decoder<Type, Layer>::value;
243 
244  template<typename Type, typename Layer>
245  constexpr bool use_decode_constructor =
246  is_layer_constructible<Type, Layer>::value
247  && !has_decode_layer_method<Type, Layer>::value
248  && !has_explicit_decoder<Type, Layer>::value;
249 
250  template<typename Type, typename Layer>
251  constexpr bool use_explicit_encoder = has_explicit_encoder<Type, Layer>::value;
252 
253  template<typename Type, typename Layer>
254  constexpr bool use_encode_layer_method =
255  has_encode_layer_method<Type, Layer>::value
256  && !has_explicit_encoder<Type, Layer>::value;
257  }
258 
259  template<typename Type, GARLIC_VIEW Layer>
260  static inline std::enable_if_t<internal::use_decode_layer_method<Type, Layer>, Type>
261  decode(Layer&& layer) { return Type::decode(layer); }
262 
263  template<typename Type, GARLIC_VIEW Layer>
264  static inline std::enable_if_t<internal::use_decode_constructor<Type, Layer>, Type>
265  decode(Layer&& layer) { return Type(layer); }
266 
268 
273  template<typename Type, GARLIC_VIEW Layer>
274  static inline std::enable_if_t<internal::use_explicit_decoder<Type, Layer>, Type>
275  decode(Layer&& layer) { return coder<Type>::decode(layer); }
276 
277  template<typename Type, GARLIC_VIEW Layer, typename Callable>
278  static inline std::enable_if_t<internal::use_explicit_safe_decoder<Type, Layer>>
279  safe_decode(Layer&& layer, Callable&& cb) {
280  coder<Type>::safe_decode(layer, cb);
281  }
282 
284 
290  template<typename Type, GARLIC_VIEW Layer, typename Callable>
291  static inline std::enable_if_t<internal::use_safe_decode_layer_method<Type, Layer>>
292  safe_decode(Layer&& layer, Callable&& cb) {
293  Type::safe_decode(layer, cb);
294  }
295 
296  template<GARLIC_REF Layer, typename Type>
297  static inline std::enable_if_t<internal::use_explicit_encoder<Type, Layer>>
298  encode(Layer&& layer, const Type& value) {
299  coder<Type>::encode(layer, value);
300  }
301 
303 
310  template<GARLIC_REF Layer, typename Type>
311  static inline std::enable_if_t<internal::use_encode_layer_method<Type, Layer>>
312  encode(Layer&& layer, const Type& value) {
313  Type::encode(layer, value);
314  }
315 
316 }
317 
318 #endif /* end of include guard: GARLIC_ENCODING_H */
layer.h
This file contains concepts for C++ 20 along with some helper types to make it easier to produce iter...
containers.h
Supporting containers for the garlic model.