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 : }