My Project
Loading...
Searching...
No Matches
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 3 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 <cstdint>
26#include <functional>
27#include <map>
28#include <memory>
29#include <optional>
30#include <set>
31#include <stdexcept>
32#include <type_traits>
33#include <utility>
34#include <unordered_map>
35#include <unordered_set>
36#include <variant>
37#include <vector>
38
39#if HAVE_DUNE_COMMON
40namespace Dune { template<typename,int> class FieldVector; }
41#endif
42
43#if HAVE_DUNE_ISTL
44namespace Dune { template<typename,typename> class BlockVector; }
45#endif
46
47namespace Opm {
48namespace detail {
49
50template<typename ...Ts>
52{
53
54template<std::size_t Index, typename, typename ...Rest>
55static decltype(auto) make_variant(std::size_t index)
56{
57 if(Index == index)
58 return std::variant<Ts...>{std::in_place_index_t<Index>{}};
59
60 if constexpr(sizeof...(Rest) != 0)
61 return make_variant<Index + 1, Rest...>(index);
62 else
63 throw std::runtime_error("Invalid variant index");
64}
65
66};
67
68template<typename ...Ts>
69decltype(auto) make_variant(std::size_t index)
70{
71 return detail::MakeVariantImpl<Ts...>::template make_variant<0, Ts...>(index);
72}
73
74template<class T>
75using remove_cvr_t = std::remove_cv_t<std::remove_reference_t<T>>;
76
77template <typename T>
78struct is_unique_ptr : std::false_type {};
79
80template <typename T>
81struct is_unique_ptr<std::unique_ptr<T>> : std::true_type {};
82
83template <typename T>
84constexpr bool is_pod_v = std::is_standard_layout_v<T> && std::is_trivial_v<T>;
85
86} // namespace detail
87
93template<class Packer>
95public:
98 explicit Serializer(const Packer& packer) :
100 {}
101
103 template<class T>
104 void operator()(const T& data)
105 {
106 if constexpr (is_ptr<T>::value) {
107 if constexpr (detail::is_unique_ptr<T>::value) {
108 unique_ptr(data);
109 } else {
110 shared_ptr(data);
111 }
112 } else if constexpr (is_pair_or_tuple<T>::value) {
113 tuple(data);
114 } else if constexpr (is_variant<T>::value) {
115 variant(data);
116 } else if constexpr (is_optional<T>::value) {
117 optional(data);
118 } else if constexpr (is_vector<T>::value) {
119 vector(data);
120 } else if constexpr (is_map<T>::value) {
121 map(data);
122 } else if constexpr (is_array<T>::value) {
123 array(data);
124 } else if constexpr (is_set<T>::value) {
125 set(data);
126 } else if constexpr (has_serializeOp<detail::remove_cvr_t<T>>::value) {
127 const_cast<T&>(data).serializeOp(*this);
128 } else {
130 m_packSize += m_packer.packSize(data);
131 else if (m_op == Operation::PACK)
132 m_packer.pack(data, m_buffer, m_position);
133 else if (m_op == Operation::UNPACK)
134 m_packer.unpack(const_cast<T&>(data), m_buffer, m_position);
135 }
136 }
137
141 template<class T>
142 void pack(const T& data)
143 {
144 m_ptrmap.clear();
146 m_packSize = 0;
147 (*this)(data);
148 m_position = 0;
149 m_buffer.resize(m_packSize);
150 m_ptrmap.clear();
152 (*this)(data);
153 m_ptrmap.clear();
154 }
155
159 template<class... Args>
160 void pack(const Args&... data)
161 {
162 m_ptrmap.clear();
164 m_packSize = 0;
165 variadic_call(data...);
166 m_position = 0;
167 m_buffer.resize(m_packSize);
168 m_ptrmap.clear();
170 variadic_call(data...);
171 m_ptrmap.clear();
172 }
173
177 template<class T>
178 void unpack(T& data)
179 {
180 m_position = 0;
181 m_ptrmap.clear();
183 (*this)(data);
184 m_ptrmap.clear();
185 }
186
190 template<class... Args>
191 void unpack(Args&... data)
192 {
193 m_position = 0;
194 m_ptrmap.clear();
196 variadic_call(data...);
197 m_ptrmap.clear();
198 }
199
201 size_t position() const
202 {
203 return m_position;
204 }
205
207 bool isSerializing() const
208 {
209 return m_op != Operation::UNPACK;
210 }
211
212protected:
216 template <typename Vector>
217 void vector(const Vector& data)
218 {
219 if constexpr (detail::is_pod_v<typename Vector::value_type>) {
220 if (m_op == Operation::PACKSIZE) {
221 (*this)(data.size());
222 if (data.size() > 0) {
223 m_packSize += m_packer.packSize(data.data(), data.size());
224 }
225 } else if (m_op == Operation::PACK) {
226 (*this)(data.size());
227 if (data.size() > 0) {
228 m_packer.pack(data.data(), data.size(), m_buffer, m_position);
229 }
230 } else if (m_op == Operation::UNPACK) {
231 std::size_t size = 0;
232 (*this)(size);
233 auto& data_mut = const_cast<Vector&>(data);
234 data_mut.resize(size);
235 if (size > 0) {
236 m_packer.unpack(data_mut.data(), size, m_buffer, m_position);
237 }
238 }
239 } else {
240 if (m_op == Operation::UNPACK) {
241 std::size_t size = 0;
242 (*this)(size);
243 auto& data_mut = const_cast<Vector&>(data);
244 data_mut.resize(size);
245 std::for_each(data_mut.begin(), data_mut.end(), std::ref(*this));
246 } else {
247 (*this)(data.size());
248 std::for_each(data.begin(), data.end(), std::ref(*this));
249 }
250 }
251 }
252
255 void vector(const std::vector<bool>& data)
256 {
257 if (m_op == Operation::UNPACK) {
258 std::size_t size = 0;
259 (*this)(size);
260 auto& data_mut = const_cast<std::vector<bool>&>(data);
261 data_mut.clear();
262 data_mut.reserve(size);
263 for (size_t i = 0; i < size; ++i) {
264 bool entry = false;
265 (*this)(entry);
266 data_mut.push_back(entry);
267 }
268 } else {
269 (*this)(data.size());
270 for (const auto entry : data) { // Not a reference: vector<bool> range
271 bool b = entry;
272 (*this)(b);
273 }
274 }
275 }
276
279 template <class Array>
280 void array(const Array& data)
281 {
282 using T = typename Array::value_type;
283
284 if constexpr (detail::is_pod_v<T>) {
286 m_packSize += m_packer.packSize(data.data(), data.size());
287 else if (m_op == Operation::PACK)
288 m_packer.pack(data.data(), data.size(), m_buffer, m_position);
289 else if (m_op == Operation::UNPACK) {
290 auto& data_mut = const_cast<Array&>(data);
291 m_packer.unpack(data_mut.data(), data_mut.size(), m_buffer, m_position);
292 }
293 } else {
294 std::for_each(data.begin(), data.end(), std::ref(*this));
295 }
296 }
297
300 template<class... Args>
301 void variant(const std::variant<Args...>& data)
302 {
303 if (m_op == Operation::UNPACK) {
304 std::size_t index = 0;
305 (*this)(index);
306 auto& data_mut = const_cast<std::variant<Args...>&>(data);
307 data_mut = detail::make_variant<Args...>(index);
308 std::visit(std::ref(*this), data_mut);
309 } else {
310 (*this)(data.index());
311 std::visit(std::ref(*this), data);
312 }
313 }
314
318 template<class T>
319 void optional(const std::optional<T>& data)
320 {
321 if (m_op == Operation::UNPACK) {
322 bool has = false;
323 (*this)(has);
324 if (has) {
325 T res{};
326 (*this)(res);
327 const_cast<std::optional<T>&>(data) = res;
328 } else {
329 const_cast<std::optional<T>&>(data) = std::nullopt;
330 }
331 } else {
332 (*this)(data.has_value());
333 if (data.has_value()) {
334 (*this)(*data);
335 }
336 }
337 }
338
341 template<class Tuple>
342 void tuple(const Tuple& data)
343 {
344 tuple_call(data);
345 }
346
350 template<class Map>
351 void map(const Map& data)
352 {
353 if (m_op == Operation::UNPACK) {
354 std::size_t size = 0;
355 (*this)(size);
356 auto& data_mut = const_cast<Map&>(data);
357 for (size_t i = 0; i < size; ++i) {
358 typename Map::value_type entry;
359 (*this)(entry);
360 data_mut.insert(std::move(entry));
361 }
362 } else {
363 (*this)(data.size());
364 std::for_each(data.begin(), data.end(), std::ref(*this));
365 }
366 }
367
371 template<class Set>
372 void set(const Set& data)
373 {
374 if (m_op == Operation::UNPACK) {
375 std::size_t size = 0;
376 (*this)(size);
377 auto& data_mut = const_cast<Set&>(data);
378 for (size_t i = 0; i < size; ++i) {
379 typename Set::value_type entry{};
380 (*this)(entry);
381 data_mut.insert(entry);
382 }
383 } else {
384 (*this)(data.size());
385 std::for_each(data.begin(), data.end(), std::ref(*this));
386 }
387 }
388
389 template<typename T, typename... Args>
390 void variadic_call(T& first,
391 Args&&... args)
392 {
393 (*this)(first);
394 if constexpr (sizeof...(args) > 0)
395 variadic_call(std::forward<Args>(args)...);
396 }
397
398 template<std::size_t I = 0, typename Tuple>
399 typename std::enable_if<I == std::tuple_size<Tuple>::value, void>::type
400 tuple_call(const Tuple&)
401 {
402 }
403
404 template<std::size_t I = 0, typename Tuple>
405 typename std::enable_if<I != std::tuple_size<Tuple>::value, void>::type
406 tuple_call(const Tuple& tuple)
407 {
408 (*this)(std::get<I>(tuple));
410 }
411
413 enum class Operation {
414 PACKSIZE,
415 PACK,
416 UNPACK
417 };
418
420 template<class T>
421 struct is_vector {
422 constexpr static bool value = false;
423 };
424
425 template<class T1, class Allocator>
426 struct is_vector<std::vector<T1,Allocator>> {
427 constexpr static bool value = true;
428 };
429
430#if HAVE_DUNE_ISTL
431 template<class T1, class Allocator>
432 struct is_vector<Dune::BlockVector<T1,Allocator>> {
433 constexpr static bool value = true;
434 };
435#endif
436
438 template<class T>
439 struct is_variant {
440 constexpr static bool value = false;
441 };
442
443 template<class... Ts>
444 struct is_variant<std::variant<Ts...>> {
445 constexpr static bool value = true;
446 };
447
449 template<class T>
451 constexpr static bool value = false;
452 };
453
454 template<class... Ts>
455 struct is_pair_or_tuple<std::tuple<Ts...>> {
456 constexpr static bool value = true;
457 };
458
459 template<class T1, class T2>
460 struct is_pair_or_tuple<std::pair<T1,T2>> {
461 constexpr static bool value = true;
462 };
463
465 template<class T>
466 struct is_ptr {
467 constexpr static bool value = false;
468 };
469
470 template<class T1>
471 struct is_ptr<std::shared_ptr<T1>> {
472 constexpr static bool value = true;
473 };
474
475 template<class T1, class Deleter>
476 struct is_ptr<std::unique_ptr<T1, Deleter>> {
477 constexpr static bool value = true;
478 };
479
481 template<class T>
482 struct is_optional {
483 constexpr static bool value = false;
484 };
485
486 template<class T1>
487 struct is_optional<std::optional<T1>> {
488 constexpr static bool value = true;
489 };
490
492 template<class T>
493 struct is_map {
494 constexpr static bool value = false;
495 };
496
497 template<class Key, class T, class Compare, class Allocator>
498 struct is_map<std::map<Key,T,Compare,Allocator>> {
499 constexpr static bool value = true;
500 };
501
502 template<class Key, class T, class Hash, class KeyEqual, class Allocator>
503 struct is_map<std::unordered_map<Key,T,Hash,KeyEqual,Allocator>> {
504 constexpr static bool value = true;
505 };
506
508 template<class T>
509 struct is_set {
510 constexpr static bool value = false;
511 };
512
513 template<class Key, class Compare, class Allocator>
514 struct is_set<std::set<Key,Compare,Allocator>> {
515 constexpr static bool value = true;
516 };
517
518 template<class Key, class Hash, class KeyEqual, class Allocator>
519 struct is_set<std::unordered_set<Key,Hash,KeyEqual,Allocator>> {
520 constexpr static bool value = true;
521 };
522
524 template<class T>
525 struct is_array {
526 constexpr static bool value = false;
527 };
528
529 template<class T, std::size_t N>
530 struct is_array<std::array<T,N>> {
531 constexpr static bool value = true;
532 };
533
534#if HAVE_DUNE_COMMON
535 template<class T, int N>
536 struct is_array<Dune::FieldVector<T,N>> {
537 constexpr static bool value = true;
538 };
539#endif
540
544 template <typename, class = void>
545 struct has_serializeOp : public std::false_type {};
546
551 template <typename T>
553 T, std::void_t<decltype(std::declval<T>().serializeOp(std::declval<Serializer<Packer>&>()))>
554 > : public std::true_type {};
555
557 template<class PtrType>
558 void shared_ptr(const PtrType& data)
559 {
560 using T1 = typename PtrType::element_type;
561 std::uintptr_t data_ptr = reinterpret_cast<std::uintptr_t>(data.get());
562 (*this)(data_ptr);
563 if (!data_ptr)
564 return;
566 if (m_ptrmap.count(data_ptr) == 0) {
567 (*this)(*data);
568 m_ptrmap[data_ptr].reset();
569 }
570 } else { // m_op == Operation::UNPACK
571 if (m_ptrmap.count(data_ptr) == 0) {
572 const_cast<PtrType&>(data) = std::make_shared<T1>();
573 m_ptrmap[data_ptr] = std::static_pointer_cast<void>(data);
574 (*this)(*data);
575 } else {
576 const_cast<PtrType&>(data) = std::static_pointer_cast<T1>(m_ptrmap[data_ptr]);
577 }
578 }
579 }
580
581 template<class PtrType>
582 void unique_ptr(const PtrType& data)
583 {
584 using T1 = typename PtrType::element_type;
585
586 if (m_op != Operation::UNPACK) {
587 (*this)(data ? 1 : 0);
588 if (data) {
589 (*this)(*data);
590 }
591 } else {
592 int ptr = 0;
593 (*this)(ptr);
594 if (ptr == 1) {
595 const_cast<PtrType&>(data) = std::make_unique<T1>();
596 (*this)(*data);
597 }
598 }
599 }
600
603 size_t m_packSize = 0;
604 size_t m_position = 0;
605 std::vector<char> m_buffer;
606 std::map<std::uintptr_t, std::shared_ptr<void>> m_ptrmap;
607};
608
609}
610
611#endif
Class for (de-)serializing.
Definition Serializer.hpp:94
size_t m_position
Current position in buffer.
Definition Serializer.hpp:604
void array(const Array &data)
Handler for arrays.
Definition Serializer.hpp:280
void operator()(const T &data)
Applies current serialization op to the passed data.
Definition Serializer.hpp:104
bool isSerializing() const
Returns true if we are currently doing a serialization operation.
Definition Serializer.hpp:207
const Packer & m_packer
Packer to use.
Definition Serializer.hpp:601
void tuple(const Tuple &data)
Handler for std::tuple.
Definition Serializer.hpp:342
void set(const Set &data)
Handler for sets.
Definition Serializer.hpp:372
Operation
Enumeration of operations.
Definition Serializer.hpp:413
@ 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:178
void shared_ptr(const PtrType &data)
Handler for shared pointers.
Definition Serializer.hpp:558
size_t position() const
Returns current position in buffer.
Definition Serializer.hpp:201
size_t m_packSize
Required buffer size after PACKSIZE has been done.
Definition Serializer.hpp:603
void pack(const Args &... data)
Call this to serialize data.
Definition Serializer.hpp:160
void unpack(Args &... data)
Call this to de-serialize data.
Definition Serializer.hpp:191
void vector(const Vector &data)
Handler for vectors.
Definition Serializer.hpp:217
void vector(const std::vector< bool > &data)
Handler for bool vectors.
Definition Serializer.hpp:255
Serializer(const Packer &packer)
Constructor.
Definition Serializer.hpp:98
void variant(const std::variant< Args... > &data)
Handler for std::variant.
Definition Serializer.hpp:301
void map(const Map &data)
Handler for maps.
Definition Serializer.hpp:351
void pack(const T &data)
Call this to serialize data.
Definition Serializer.hpp:142
Operation m_op
Current operation.
Definition Serializer.hpp:602
void optional(const std::optional< T > &data)
Handler for std::optional.
Definition Serializer.hpp:319
std::vector< char > m_buffer
Buffer for serialized data.
Definition Serializer.hpp:605
std::map< std::uintptr_t, std::shared_ptr< void > > m_ptrmap
Map to keep track of which pointer data has been serialized and actual pointers during unpacking.
Definition Serializer.hpp:606
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30
Detect existence of serializeOp member function.
Definition Serializer.hpp:545
Predicate for arrays.
Definition Serializer.hpp:525
Predicate for maps.
Definition Serializer.hpp:493
Predicate for std::optional.
Definition Serializer.hpp:482
Predicate for detecting pairs and tuples.
Definition Serializer.hpp:450
Predicate for smart pointers.
Definition Serializer.hpp:466
Predicate for sets.
Definition Serializer.hpp:509
Predicate for detecting variants.
Definition Serializer.hpp:439
Predicate for detecting vectors.
Definition Serializer.hpp:421
Definition Serializer.hpp:52
Definition Serializer.hpp:78