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
83} // namespace detail
84
90template<class Packer>
92public:
95 explicit Serializer(const Packer& packer) :
97 {}
98
100 template<class T>
101 void operator()(const T& data)
102 {
103 if constexpr (is_ptr<T>::value) {
104 if constexpr (detail::is_unique_ptr<T>::value) {
105 unique_ptr(data);
106 } else {
107 shared_ptr(data);
108 }
109 } else if constexpr (is_pair_or_tuple<T>::value) {
110 tuple(data);
111 } else if constexpr (is_variant<T>::value) {
112 variant(data);
113 } else if constexpr (is_optional<T>::value) {
114 optional(data);
115 } else if constexpr (is_vector<T>::value) {
116 vector(data);
117 } else if constexpr (is_map<T>::value) {
118 map(data);
119 } else if constexpr (is_array<T>::value) {
120 array(data);
121 } else if constexpr (is_set<T>::value) {
122 set(data);
123 } else if constexpr (has_serializeOp<detail::remove_cvr_t<T>>::value) {
124 const_cast<T&>(data).serializeOp(*this);
125 } else {
127 m_packSize += m_packer.packSize(data);
128 else if (m_op == Operation::PACK)
129 m_packer.pack(data, m_buffer, m_position);
130 else if (m_op == Operation::UNPACK)
131 m_packer.unpack(const_cast<T&>(data), m_buffer, m_position);
132 }
133 }
134
138 template<class T>
139 void pack(const T& data)
140 {
141 m_ptrmap.clear();
143 m_packSize = 0;
144 (*this)(data);
145 m_position = 0;
146 m_buffer.resize(m_packSize);
147 m_ptrmap.clear();
149 (*this)(data);
150 m_ptrmap.clear();
151 }
152
156 template<class... Args>
157 void pack(const Args&... data)
158 {
159 m_ptrmap.clear();
161 m_packSize = 0;
162 variadic_call(data...);
163 m_position = 0;
164 m_buffer.resize(m_packSize);
165 m_ptrmap.clear();
167 variadic_call(data...);
168 m_ptrmap.clear();
169 }
170
174 template<class T>
175 void unpack(T& data)
176 {
177 m_position = 0;
178 m_ptrmap.clear();
180 (*this)(data);
181 m_ptrmap.clear();
182 }
183
187 template<class... Args>
188 void unpack(Args&... data)
189 {
190 m_position = 0;
191 m_ptrmap.clear();
193 variadic_call(data...);
194 m_ptrmap.clear();
195 }
196
198 size_t position() const
199 {
200 return m_position;
201 }
202
204 bool isSerializing() const
205 {
206 return m_op != Operation::UNPACK;
207 }
208
209protected:
213 template <typename Vector>
214 void vector(const Vector& data)
215 {
216 if constexpr (std::is_pod_v<typename Vector::value_type>) {
217 if (m_op == Operation::PACKSIZE) {
218 (*this)(data.size());
219 if (data.size() > 0) {
220 m_packSize += m_packer.packSize(data.data(), data.size());
221 }
222 } else if (m_op == Operation::PACK) {
223 (*this)(data.size());
224 if (data.size() > 0) {
225 m_packer.pack(data.data(), data.size(), m_buffer, m_position);
226 }
227 } else if (m_op == Operation::UNPACK) {
228 std::size_t size = 0;
229 (*this)(size);
230 auto& data_mut = const_cast<Vector&>(data);
231 data_mut.resize(size);
232 if (size > 0) {
233 m_packer.unpack(data_mut.data(), size, m_buffer, m_position);
234 }
235 }
236 } else {
237 if (m_op == Operation::UNPACK) {
238 std::size_t size = 0;
239 (*this)(size);
240 auto& data_mut = const_cast<Vector&>(data);
241 data_mut.resize(size);
242 std::for_each(data_mut.begin(), data_mut.end(), std::ref(*this));
243 } else {
244 (*this)(data.size());
245 std::for_each(data.begin(), data.end(), std::ref(*this));
246 }
247 }
248 }
249
252 void vector(const std::vector<bool>& data)
253 {
254 if (m_op == Operation::UNPACK) {
255 std::size_t size = 0;
256 (*this)(size);
257 auto& data_mut = const_cast<std::vector<bool>&>(data);
258 data_mut.clear();
259 data_mut.reserve(size);
260 for (size_t i = 0; i < size; ++i) {
261 bool entry = false;
262 (*this)(entry);
263 data_mut.push_back(entry);
264 }
265 } else {
266 (*this)(data.size());
267 for (const auto entry : data) { // Not a reference: vector<bool> range
268 bool b = entry;
269 (*this)(b);
270 }
271 }
272 }
273
276 template <class Array>
277 void array(const Array& data)
278 {
279 using T = typename Array::value_type;
280
281 if constexpr (std::is_pod_v<T>) {
283 m_packSize += m_packer.packSize(data.data(), data.size());
284 else if (m_op == Operation::PACK)
285 m_packer.pack(data.data(), data.size(), m_buffer, m_position);
286 else if (m_op == Operation::UNPACK) {
287 auto& data_mut = const_cast<Array&>(data);
288 m_packer.unpack(data_mut.data(), data_mut.size(), m_buffer, m_position);
289 }
290 } else {
291 std::for_each(data.begin(), data.end(), std::ref(*this));
292 }
293 }
294
297 template<class... Args>
298 void variant(const std::variant<Args...>& data)
299 {
300 if (m_op == Operation::UNPACK) {
301 std::size_t index = 0;
302 (*this)(index);
303 auto& data_mut = const_cast<std::variant<Args...>&>(data);
304 data_mut = detail::make_variant<Args...>(index);
305 std::visit(std::ref(*this), data_mut);
306 } else {
307 (*this)(data.index());
308 std::visit(std::ref(*this), data);
309 }
310 }
311
315 template<class T>
316 void optional(const std::optional<T>& data)
317 {
318 if (m_op == Operation::UNPACK) {
319 bool has = false;
320 (*this)(has);
321 if (has) {
322 T res{};
323 (*this)(res);
324 const_cast<std::optional<T>&>(data) = res;
325 } else {
326 const_cast<std::optional<T>&>(data) = std::nullopt;
327 }
328 } else {
329 (*this)(data.has_value());
330 if (data.has_value()) {
331 (*this)(*data);
332 }
333 }
334 }
335
338 template<class Tuple>
339 void tuple(const Tuple& data)
340 {
341 tuple_call(data);
342 }
343
347 template<class Map>
348 void map(const Map& data)
349 {
350 if (m_op == Operation::UNPACK) {
351 std::size_t size = 0;
352 (*this)(size);
353 auto& data_mut = const_cast<Map&>(data);
354 for (size_t i = 0; i < size; ++i) {
355 typename Map::value_type entry;
356 (*this)(entry);
357 data_mut.insert(entry);
358 }
359 } else {
360 (*this)(data.size());
361 std::for_each(data.begin(), data.end(), std::ref(*this));
362 }
363 }
364
368 template<class Set>
369 void set(const Set& data)
370 {
371 if (m_op == Operation::UNPACK) {
372 std::size_t size = 0;
373 (*this)(size);
374 auto& data_mut = const_cast<Set&>(data);
375 for (size_t i = 0; i < size; ++i) {
376 typename Set::value_type entry{};
377 (*this)(entry);
378 data_mut.insert(entry);
379 }
380 } else {
381 (*this)(data.size());
382 std::for_each(data.begin(), data.end(), std::ref(*this));
383 }
384 }
385
386 template<typename T, typename... Args>
387 void variadic_call(T& first,
388 Args&&... args)
389 {
390 (*this)(first);
391 if constexpr (sizeof...(args) > 0)
392 variadic_call(std::forward<Args>(args)...);
393 }
394
395 template<std::size_t I = 0, typename Tuple>
396 typename std::enable_if<I == std::tuple_size<Tuple>::value, void>::type
397 tuple_call(const Tuple&)
398 {
399 }
400
401 template<std::size_t I = 0, typename Tuple>
402 typename std::enable_if<I != std::tuple_size<Tuple>::value, void>::type
403 tuple_call(const Tuple& tuple)
404 {
405 (*this)(std::get<I>(tuple));
407 }
408
410 enum class Operation {
411 PACKSIZE,
412 PACK,
413 UNPACK
414 };
415
417 template<class T>
418 struct is_vector {
419 constexpr static bool value = false;
420 };
421
422 template<class T1, class Allocator>
423 struct is_vector<std::vector<T1,Allocator>> {
424 constexpr static bool value = true;
425 };
426
427#if HAVE_DUNE_ISTL
428 template<class T1, class Allocator>
429 struct is_vector<Dune::BlockVector<T1,Allocator>> {
430 constexpr static bool value = true;
431 };
432#endif
433
435 template<class T>
436 struct is_variant {
437 constexpr static bool value = false;
438 };
439
440 template<class... Ts>
441 struct is_variant<std::variant<Ts...>> {
442 constexpr static bool value = true;
443 };
444
446 template<class T>
448 constexpr static bool value = false;
449 };
450
451 template<class... Ts>
452 struct is_pair_or_tuple<std::tuple<Ts...>> {
453 constexpr static bool value = true;
454 };
455
456 template<class T1, class T2>
457 struct is_pair_or_tuple<std::pair<T1,T2>> {
458 constexpr static bool value = true;
459 };
460
462 template<class T>
463 struct is_ptr {
464 constexpr static bool value = false;
465 };
466
467 template<class T1>
468 struct is_ptr<std::shared_ptr<T1>> {
469 constexpr static bool value = true;
470 };
471
472 template<class T1, class Deleter>
473 struct is_ptr<std::unique_ptr<T1, Deleter>> {
474 constexpr static bool value = true;
475 };
476
478 template<class T>
479 struct is_optional {
480 constexpr static bool value = false;
481 };
482
483 template<class T1>
484 struct is_optional<std::optional<T1>> {
485 constexpr static bool value = true;
486 };
487
489 template<class T>
490 struct is_map {
491 constexpr static bool value = false;
492 };
493
494 template<class Key, class T, class Compare, class Allocator>
495 struct is_map<std::map<Key,T,Compare,Allocator>> {
496 constexpr static bool value = true;
497 };
498
499 template<class Key, class T, class Hash, class KeyEqual, class Allocator>
500 struct is_map<std::unordered_map<Key,T,Hash,KeyEqual,Allocator>> {
501 constexpr static bool value = true;
502 };
503
505 template<class T>
506 struct is_set {
507 constexpr static bool value = false;
508 };
509
510 template<class Key, class Compare, class Allocator>
511 struct is_set<std::set<Key,Compare,Allocator>> {
512 constexpr static bool value = true;
513 };
514
515 template<class Key, class Hash, class KeyEqual, class Allocator>
516 struct is_set<std::unordered_set<Key,Hash,KeyEqual,Allocator>> {
517 constexpr static bool value = true;
518 };
519
521 template<class T>
522 struct is_array {
523 constexpr static bool value = false;
524 };
525
526 template<class T, std::size_t N>
527 struct is_array<std::array<T,N>> {
528 constexpr static bool value = true;
529 };
530
531#if HAVE_DUNE_COMMON
532 template<class T, int N>
533 struct is_array<Dune::FieldVector<T,N>> {
534 constexpr static bool value = true;
535 };
536#endif
537
541 template <typename, class = void>
542 struct has_serializeOp : public std::false_type {};
543
548 template <typename T>
550 T, std::void_t<decltype(std::declval<T>().serializeOp(std::declval<Serializer<Packer>&>()))>
551 > : public std::true_type {};
552
554 template<class PtrType>
555 void shared_ptr(const PtrType& data)
556 {
557 using T1 = typename PtrType::element_type;
558 std::uintptr_t data_ptr = reinterpret_cast<std::uintptr_t>(data.get());
559 (*this)(data_ptr);
560 if (!data_ptr)
561 return;
563 if (m_ptrmap.count(data_ptr) == 0) {
564 (*this)(*data);
565 m_ptrmap[data_ptr].reset();
566 }
567 } else { // m_op == Operation::UNPACK
568 if (m_ptrmap.count(data_ptr) == 0) {
569 const_cast<PtrType&>(data) = std::make_shared<T1>();
570 m_ptrmap[data_ptr] = std::static_pointer_cast<void>(data);
571 (*this)(*data);
572 } else {
573 const_cast<PtrType&>(data) = std::static_pointer_cast<T1>(m_ptrmap[data_ptr]);
574 }
575 }
576 }
577
578 template<class PtrType>
579 void unique_ptr(const PtrType& data)
580 {
581 using T1 = typename PtrType::element_type;
582
583 if (m_op != Operation::UNPACK) {
584 (*this)(data ? 1 : 0);
585 if (data) {
586 (*this)(*data);
587 }
588 } else {
589 int ptr = 0;
590 (*this)(ptr);
591 if (ptr == 1) {
592 const_cast<PtrType&>(data) = std::make_unique<T1>();
593 (*this)(*data);
594 }
595 }
596 }
597
600 size_t m_packSize = 0;
601 size_t m_position = 0;
602 std::vector<char> m_buffer;
603 std::map<std::uintptr_t, std::shared_ptr<void>> m_ptrmap;
604};
605
606}
607
608#endif
Class for (de-)serializing.
Definition Serializer.hpp:91
size_t m_position
Current position in buffer.
Definition Serializer.hpp:601
void array(const Array &data)
Handler for arrays.
Definition Serializer.hpp:277
void operator()(const T &data)
Applies current serialization op to the passed data.
Definition Serializer.hpp:101
bool isSerializing() const
Returns true if we are currently doing a serialization operation.
Definition Serializer.hpp:204
const Packer & m_packer
Packer to use.
Definition Serializer.hpp:598
void tuple(const Tuple &data)
Handler for std::tuple.
Definition Serializer.hpp:339
void set(const Set &data)
Handler for sets.
Definition Serializer.hpp:369
Operation
Enumeration of operations.
Definition Serializer.hpp:410
@ 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:175
void shared_ptr(const PtrType &data)
Handler for shared pointers.
Definition Serializer.hpp:555
size_t position() const
Returns current position in buffer.
Definition Serializer.hpp:198
size_t m_packSize
Required buffer size after PACKSIZE has been done.
Definition Serializer.hpp:600
void pack(const Args &... data)
Call this to serialize data.
Definition Serializer.hpp:157
void unpack(Args &... data)
Call this to de-serialize data.
Definition Serializer.hpp:188
void vector(const Vector &data)
Handler for vectors.
Definition Serializer.hpp:214
void vector(const std::vector< bool > &data)
Handler for bool vectors.
Definition Serializer.hpp:252
Serializer(const Packer &packer)
Constructor.
Definition Serializer.hpp:95
void variant(const std::variant< Args... > &data)
Handler for std::variant.
Definition Serializer.hpp:298
void map(const Map &data)
Handler for maps.
Definition Serializer.hpp:348
void pack(const T &data)
Call this to serialize data.
Definition Serializer.hpp:139
Operation m_op
Current operation.
Definition Serializer.hpp:599
void optional(const std::optional< T > &data)
Handler for std::optional.
Definition Serializer.hpp:316
std::vector< char > m_buffer
Buffer for serialized data.
Definition Serializer.hpp:602
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:603
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:542
Predicate for arrays.
Definition Serializer.hpp:522
Predicate for maps.
Definition Serializer.hpp:490
Predicate for std::optional.
Definition Serializer.hpp:479
Predicate for detecting pairs and tuples.
Definition Serializer.hpp:447
Predicate for smart pointers.
Definition Serializer.hpp:463
Predicate for sets.
Definition Serializer.hpp:506
Predicate for detecting variants.
Definition Serializer.hpp:436
Predicate for detecting vectors.
Definition Serializer.hpp:418
Definition Serializer.hpp:52
Definition Serializer.hpp:78