My Project
Serializer.hpp
1/*
2 This file is part of the Open Porous Media project (OPM).
3
4 OPM is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 2 of the License, or
7 (at your option) any later version.
8
9 OPM is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with OPM. If not, see <http://www.gnu.org/licenses/>.
16
17 Consult the COPYING file in the top-level source directory of this
18 module for the precise wording of the license and the list of
19 copyright holders.
20*/
21#ifndef SERIALIZER_HPP
22#define SERIALIZER_HPP
23
24#include <algorithm>
25#include <functional>
26#include <map>
27#include <memory>
28#include <optional>
29#include <set>
30#include <type_traits>
31#include <utility>
32#include <unordered_map>
33#include <unordered_set>
34#include <variant>
35#include <vector>
36
37namespace Opm {
38namespace detail {
39
40template<typename ...Ts>
42{
43
44template<std::size_t Index, typename, typename ...Rest>
45static decltype(auto) make_variant(std::size_t index)
46{
47 if(Index == index)
48 return std::variant<Ts...>{std::in_place_index_t<Index>{}};
49
50 if constexpr(sizeof...(Rest) != 0)
51 return make_variant<Index + 1, Rest...>(index);
52 else
53 throw std::runtime_error("Invalid variant index");
54}
55
56};
57
58template<typename ...Ts>
59decltype(auto) make_variant(std::size_t index)
60{
61 return detail::MakeVariantImpl<Ts...>::template make_variant<0, Ts...>(index);
62}
63
64template<class T>
65using remove_cvr_t = std::remove_cv_t<std::remove_reference_t<T>>;
66
67} // namespace detail
68
74template<class Packer>
76public:
79 explicit Serializer(const Packer& packer) :
80 m_packer(packer)
81 {}
82
84 template<class T>
85 void operator()(const T& data)
86 {
87 if constexpr (is_ptr<T>::value) {
88 ptr(data);
89 } else if constexpr (is_pair_or_tuple<T>::value) {
90 tuple(data);
91 } else if constexpr (is_variant<T>::value) {
92 variant(data);
93 } else if constexpr (is_optional<T>::value) {
94 optional(data);
95 } else if constexpr (is_vector<T>::value) {
96 vector(data);
97 } else if constexpr (is_map<T>::value) {
98 map(data);
99 } else if constexpr (is_array<T>::value) {
100 array(data);
101 } else if constexpr (is_set<T>::value) {
102 set(data);
103 } else if constexpr (has_serializeOp<detail::remove_cvr_t<T>>::value) {
104 const_cast<T&>(data).serializeOp(*this);
105 } else {
107 m_packSize += m_packer.packSize(data);
108 else if (m_op == Operation::PACK)
109 m_packer.pack(data, m_buffer, m_position);
110 else if (m_op == Operation::UNPACK)
111 m_packer.unpack(const_cast<T&>(data), m_buffer, m_position);
112 }
113 }
114
118 template<class T>
119 void pack(const T& data)
120 {
122 m_packSize = 0;
123 (*this)(data);
124 m_position = 0;
125 m_buffer.resize(m_packSize);
127 (*this)(data);
128 }
129
133 template<class... Args>
134 void pack(const Args&... data)
135 {
137 m_packSize = 0;
138 variadic_call(data...);
139 m_position = 0;
140 m_buffer.resize(m_packSize);
142 variadic_call(data...);
143 }
144
148 template<class T>
149 void unpack(T& data)
150 {
151 m_position = 0;
153 (*this)(data);
154 }
155
159 template<class... Args>
160 void unpack(Args&... data)
161 {
162 m_position = 0;
164 variadic_call(data...);
165 }
166
168 size_t position() const
169 {
170 return m_position;
171 }
172
174 bool isSerializing() const
175 {
176 return m_op != Operation::UNPACK;
177 }
178
179protected:
183 template <typename T>
184 void vector(const std::vector<T>& data)
185 {
186 if constexpr (std::is_pod_v<T>) {
187 if (m_op == Operation::PACKSIZE) {
188 (*this)(data.size());
189 m_packSize += m_packer.packSize(data.data(), data.size());
190 } else if (m_op == Operation::PACK) {
191 (*this)(data.size());
192 m_packer.pack(data.data(), data.size(), m_buffer, m_position);
193 } else if (m_op == Operation::UNPACK) {
194 std::size_t size = 0;
195 (*this)(size);
196 auto& data_mut = const_cast<std::vector<T>&>(data);
197 data_mut.resize(size);
198 m_packer.unpack(data_mut.data(), size, m_buffer, m_position);
199 }
200 } else {
201 if (m_op == Operation::UNPACK) {
202 std::size_t size = 0;
203 (*this)(size);
204 auto& data_mut = const_cast<std::vector<T>&>(data);
205 data_mut.resize(size);
206 std::for_each(data_mut.begin(), data_mut.end(), std::ref(*this));
207 } else {
208 (*this)(data.size());
209 std::for_each(data.begin(), data.end(), std::ref(*this));
210 }
211 }
212 }
213
216 void vector(const std::vector<bool>& data)
217 {
218 if (m_op == Operation::UNPACK) {
219 std::size_t size = 0;
220 (*this)(size);
221 auto& data_mut = const_cast<std::vector<bool>&>(data);
222 data_mut.clear();
223 data_mut.reserve(size);
224 for (size_t i = 0; i < size; ++i) {
225 bool entry = false;
226 (*this)(entry);
227 data_mut.push_back(entry);
228 }
229 } else {
230 (*this)(data.size());
231 for (const auto entry : data) { // Not a reference: vector<bool> range
232 bool b = entry;
233 (*this)(b);
234 }
235 }
236 }
237
240 template <class Array>
241 void array(const Array& data)
242 {
243 using T = typename Array::value_type;
244
245 if constexpr (std::is_pod_v<T>) {
247 m_packSize += m_packer.packSize(data.data(), data.size());
248 else if (m_op == Operation::PACK)
249 m_packer.pack(data.data(), data.size(), m_buffer, m_position);
250 else if (m_op == Operation::UNPACK) {
251 auto& data_mut = const_cast<Array&>(data);
252 m_packer.unpack(data_mut.data(), data_mut.size(), m_buffer, m_position);
253 }
254 } else {
255 std::for_each(data.begin(), data.end(), std::ref(*this));
256 }
257 }
258
261 template<class... Args>
262 void variant(const std::variant<Args...>& data)
263 {
264 if (m_op == Operation::UNPACK) {
265 std::size_t index = 0;
266 (*this)(index);
267 auto& data_mut = const_cast<std::variant<Args...>&>(data);
268 data_mut = detail::make_variant<Args...>(index);
269 std::visit(std::ref(*this), data_mut);
270 } else {
271 (*this)(data.index());
272 std::visit(std::ref(*this), data);
273 }
274 }
275
279 template<class T>
280 void optional(const std::optional<T>& data)
281 {
282 if (m_op == Operation::UNPACK) {
283 bool has = false;
284 (*this)(has);
285 if (has) {
286 T res;
287 (*this)(res);
288 const_cast<std::optional<T>&>(data) = res;
289 }
290 } else {
291 (*this)(data.has_value());
292 if (data.has_value()) {
293 (*this)(*data);
294 }
295 }
296 }
297
300 template<class Tuple>
301 void tuple(const Tuple& data)
302 {
303 tuple_call(data);
304 }
305
309 template<class Map>
310 void map(const Map& data)
311 {
312 if (m_op == Operation::UNPACK) {
313 std::size_t size = 0;
314 (*this)(size);
315 auto& data_mut = const_cast<Map&>(data);
316 for (size_t i = 0; i < size; ++i) {
317 typename Map::value_type entry;
318 (*this)(entry);
319 data_mut.insert(entry);
320 }
321 } else {
322 (*this)(data.size());
323 std::for_each(data.begin(), data.end(), std::ref(*this));
324 }
325 }
326
330 template<class Set>
331 void set(const Set& data)
332 {
333 if (m_op == Operation::UNPACK) {
334 std::size_t size = 0;
335 (*this)(size);
336 auto& data_mut = const_cast<Set&>(data);
337 for (size_t i = 0; i < size; ++i) {
338 typename Set::value_type entry;
339 (*this)(entry);
340 data_mut.insert(entry);
341 }
342 } else {
343 (*this)(data.size());
344 std::for_each(data.begin(), data.end(), std::ref(*this));
345 }
346 }
347
348 template<typename T, typename... Args>
349 void variadic_call(T& first,
350 Args&&... args)
351 {
352 (*this)(first);
353 if constexpr (sizeof...(args) > 0)
354 variadic_call(std::forward<Args>(args)...);
355 }
356
357 template<std::size_t I = 0, typename Tuple>
358 typename std::enable_if<I == std::tuple_size<Tuple>::value, void>::type
359 tuple_call(const Tuple&)
360 {
361 }
362
363 template<std::size_t I = 0, typename Tuple>
364 typename std::enable_if<I != std::tuple_size<Tuple>::value, void>::type
365 tuple_call(const Tuple& tuple)
366 {
367 (*this)(std::get<I>(tuple));
368 tuple_call<I+1>(tuple);
369 }
370
372 enum class Operation {
373 PACKSIZE,
374 PACK,
375 UNPACK
376 };
377
379 template<class T>
380 struct is_vector {
381 constexpr static bool value = false;
382 };
383
384 template<class T1, class Allocator>
385 struct is_vector<std::vector<T1,Allocator>> {
386 constexpr static bool value = true;
387 };
388
390 template<class T>
391 struct is_variant {
392 constexpr static bool value = false;
393 };
394
395 template<class... Ts>
396 struct is_variant<std::variant<Ts...>> {
397 constexpr static bool value = true;
398 };
399
401 template<class T>
403 constexpr static bool value = false;
404 };
405
406 template<class... Ts>
407 struct is_pair_or_tuple<std::tuple<Ts...>> {
408 constexpr static bool value = true;
409 };
410
411 template<class T1, class T2>
412 struct is_pair_or_tuple<std::pair<T1,T2>> {
413 constexpr static bool value = true;
414 };
415
417 template<class T>
418 struct is_ptr {
419 constexpr static bool value = false;
420 };
421
422 template<class T1>
423 struct is_ptr<std::shared_ptr<T1>> {
424 constexpr static bool value = true;
425 };
426
427 template<class T1, class Deleter>
428 struct is_ptr<std::unique_ptr<T1, Deleter>> {
429 constexpr static bool value = true;
430 };
431
433 template<class T>
434 struct is_optional {
435 constexpr static bool value = false;
436 };
437
438 template<class T1>
439 struct is_optional<std::optional<T1>> {
440 constexpr static bool value = true;
441 };
442
444 template<class T>
445 struct is_map {
446 constexpr static bool value = false;
447 };
448
449 template<class Key, class T, class Compare, class Allocator>
450 struct is_map<std::map<Key,T,Compare,Allocator>> {
451 constexpr static bool value = true;
452 };
453
454 template<class Key, class T, class Hash, class KeyEqual, class Allocator>
455 struct is_map<std::unordered_map<Key,T,Hash,KeyEqual,Allocator>> {
456 constexpr static bool value = true;
457 };
458
460 template<class T>
461 struct is_set {
462 constexpr static bool value = false;
463 };
464
465 template<class Key, class Compare, class Allocator>
466 struct is_set<std::set<Key,Compare,Allocator>> {
467 constexpr static bool value = true;
468 };
469
470 template<class Key, class Hash, class KeyEqual, class Allocator>
471 struct is_set<std::unordered_set<Key,Hash,KeyEqual,Allocator>> {
472 constexpr static bool value = true;
473 };
474
476 template<class T>
477 struct is_array {
478 constexpr static bool value = false;
479 };
480
481 template<class T, std::size_t N>
482 struct is_array<std::array<T,N>> {
483 constexpr static bool value = true;
484 };
485
489 template <typename, class = void>
490 struct has_serializeOp : public std::false_type {};
491
496 template <typename T>
498 T, std::void_t<decltype(std::declval<T>().serializeOp(std::declval<Serializer<Packer>&>()))>
499 > : public std::true_type {};
500
502 template<class PtrType>
503 void ptr(const PtrType& data)
504 {
505 using T1 = typename PtrType::element_type;
506 bool value = data ? true : false;
507 (*this)(value);
508 if (m_op == Operation::UNPACK && value) {
509 const_cast<PtrType&>(data).reset(new T1);
510 }
511 if (data) {
512 (*this)(*data);
513 }
514 }
515
516 const Packer& m_packer;
518 size_t m_packSize = 0;
519 int m_position = 0;
520 std::vector<char> m_buffer;
521};
522
523}
524
525#endif
Class for (de-)serializing.
Definition: Serializer.hpp:75
void ptr(const PtrType &data)
Handler for smart pointers.
Definition: Serializer.hpp:503
void array(const Array &data)
Handler for arrays.
Definition: Serializer.hpp:241
void operator()(const T &data)
Applies current serialization op to the passed data.
Definition: Serializer.hpp:85
bool isSerializing() const
Returns true if we are currently doing a serialization operation.
Definition: Serializer.hpp:174
const Packer & m_packer
Packer to use.
Definition: Serializer.hpp:516
void tuple(const Tuple &data)
Handler for std::tuple.
Definition: Serializer.hpp:301
void set(const Set &data)
Handler for sets.
Definition: Serializer.hpp:331
Operation
Enumeration of operations.
Definition: Serializer.hpp:372
@ UNPACK
Performing de-serialization.
@ PACKSIZE
Calculating serialization buffer size.
@ PACK
Performing serialization.
void unpack(T &data)
Call this to de-serialize data.
Definition: Serializer.hpp:149
size_t position() const
Returns current position in buffer.
Definition: Serializer.hpp:168
void vector(const std::vector< T > &data)
Handler for vectors.
Definition: Serializer.hpp:184
size_t m_packSize
Required buffer size after PACKSIZE has been done.
Definition: Serializer.hpp:518
void pack(const Args &... data)
Call this to serialize data.
Definition: Serializer.hpp:134
void unpack(Args &... data)
Call this to de-serialize data.
Definition: Serializer.hpp:160
void vector(const std::vector< bool > &data)
Handler for bool vectors.
Definition: Serializer.hpp:216
Serializer(const Packer &packer)
Constructor.
Definition: Serializer.hpp:79
void variant(const std::variant< Args... > &data)
Handler for std::variant.
Definition: Serializer.hpp:262
void map(const Map &data)
Handler for maps.
Definition: Serializer.hpp:310
void pack(const T &data)
Call this to serialize data.
Definition: Serializer.hpp:119
Operation m_op
Current operation.
Definition: Serializer.hpp:517
void optional(const std::optional< T > &data)
Handler for std::optional.
Definition: Serializer.hpp:280
int m_position
Current position in buffer.
Definition: Serializer.hpp:519
std::vector< char > m_buffer
Buffer for serialized data.
Definition: Serializer.hpp:520
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:29
Detect existence of serializeOp member function.
Definition: Serializer.hpp:490
Predicate for arrays.
Definition: Serializer.hpp:477
Predicate for maps.
Definition: Serializer.hpp:445
Predicate for std::optional.
Definition: Serializer.hpp:434
Predicate for detecting pairs and tuples.
Definition: Serializer.hpp:402
Predicate for smart pointers.
Definition: Serializer.hpp:418
Predicate for sets.
Definition: Serializer.hpp:461
Predicate for detecting variants.
Definition: Serializer.hpp:391
Predicate for detecting vectors.
Definition: Serializer.hpp:380
Definition: Serializer.hpp:42