Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines the serialize and deserialize functions.
6 :
7 : #pragma once
8 :
9 : #include <pup.h>
10 : #include <type_traits>
11 : #include <vector>
12 :
13 : #include "Utilities/Gsl.hpp"
14 :
15 : /*!
16 : * \ingroup ParallelGroup
17 : * \brief Serialize an object using PUP.
18 : *
19 : * The type to serialize as must be explicitly specified. We require
20 : * this because a mismatch between the serialize and deserialize calls
21 : * causes undefined behavior and we do not want this to depend on
22 : * inferred types for safety.
23 : *
24 : * \tparam T type to serialize
25 : */
26 : template <typename T>
27 1 : std::vector<char> serialize(const T& obj) {
28 : const T& typed_obj = obj;
29 : // pup routine is non-const, but shouldn't modify anything in serialization
30 : // mode.
31 : // clang-tidy: do not use const_cast
32 : auto& mut_obj = const_cast<T&>(typed_obj); // NOLINT
33 :
34 : PUP::sizer sizer;
35 : sizer | mut_obj;
36 : std::vector<char> data(sizer.size());
37 : PUP::toMem writer(data.data());
38 : writer | mut_obj;
39 :
40 : return data;
41 : }
42 :
43 : /*!
44 : * \ingroup ParallelGroup
45 : * \brief Deserialize an object using PUP.
46 : *
47 : * \tparam T the type to deserialize to
48 : */
49 : template <typename T>
50 1 : T deserialize(const void* const data) { // NOLINT
51 : // clang-tidy: no const in forward decl (this is a definition)
52 : PUP::fromMem reader(data);
53 : T result{};
54 : reader | result;
55 : return result;
56 : }
57 :
58 : /*!
59 : * \ingroup ParallelGroup
60 : * \brief Deserialize an object using PUP.
61 : *
62 : * \tparam T the type to deserialize to.
63 : */
64 : template <typename T>
65 1 : void deserialize(const gsl::not_null<T*> result,
66 : const void* const data) { // NOLINT
67 : // clang-tidy: no const in forward decl (this is a definition)
68 : PUP::fromMem reader(data);
69 : reader | *result;
70 : }
71 :
72 : /*!
73 : * \ingroup ParallelGroup
74 : * \brief Returns the size of an object in bytes
75 : */
76 : template <typename T>
77 1 : size_t size_of_object_in_bytes(const T& obj) {
78 : PUP::sizer sizer;
79 : sizer | const_cast<T&>(obj); // NOLINT
80 : return sizer.size();
81 : }
82 :
83 : /*!
84 : * \ingroup ParallelGroup
85 : * \brief Serializes and deserializes an object `t` of type `T`
86 : *
87 : * Performs a PUP round-trip on `t`, returning the deserialized copy.
88 : * Useful for testing that a class is correctly serializable, and for
89 : * copying objects that store state in a way only accessible via PUP.
90 : *
91 : * \requires `T` to be default constructible.
92 : */
93 : template <typename T>
94 1 : T serialize_and_deserialize(const T& t) {
95 : static_assert(
96 : std::is_default_constructible_v<T>,
97 : "Cannot use serialize_and_deserialize if a class is not default "
98 : "constructible.");
99 : return deserialize<T>(serialize<T>(t).data());
100 : }
101 :
102 : /*!
103 : * \ingroup ParallelGroup
104 : * \brief Serializes and deserializes an object `t` of type `T` into `result`
105 : *
106 : * Performs a PUP round-trip on `t`, writing the deserialized value into
107 : * the pre-existing object pointed to by `result`.
108 : *
109 : * Unlike the value-returning overload, `T` does not need to be default
110 : * constructible, since the result is written into the pre-existing `*result`.
111 : */
112 : template <typename T>
113 1 : void serialize_and_deserialize(const gsl::not_null<T*> result, const T& t) {
114 : deserialize<T>(result, serialize<T>(t).data());
115 : }
|