/* Copyright 2021 Luca Fedeli * * This file is part of WarpX. * * License: BSD-3-Clause-LBNL */ #ifndef WARPX_MSG_LOGGER_SERIALIZATION_H_ #define WARPX_MSG_LOGGER_SERIALIZATION_H_ #include #include #include #include #include #include namespace Utils{ namespace MsgLogger{ /** * This function transforms a variable of type T into a vector of chars holding its * byte representation and it appends this vector at the end of an * existing vector of chars. T must be either a trivially copyable type or an std::string * * @tparam T the variable type * @param[in] val a variable of type T to be serialized * @param[in, out] vec a reference to the vector to which the byte representation of val is appended */ template void put_in(const T& val, std::vector& vec) { if constexpr (std::is_same()){ const char* c_str = val.c_str(); const auto length = static_cast(val.size()); put_in(length, vec); vec.insert(vec.end(), c_str, c_str+length); } else{ static_assert(std::is_trivially_copyable(), "Cannot serialize non-trivally copyable types, except std::string."); const auto* ptr_val = reinterpret_cast(&val); vec.insert(vec.end(), ptr_val, ptr_val+sizeof(T)); } } /** * This function transforms an std::vector into a vector of chars holding its * byte representation and it appends this vector at the end of an * existing vector of chars. T must be either a trivially copyable type or an std::string. * A specialization exists in case val is a vector of chars. * * @tparam T the variable type * @param[in] val a variable of type T to be serialized * @param[in, out] vec a reference to the vector to which the byte representation of val is appended */ template inline void put_in_vec (const std::vector& val, std::vector& vec) { if constexpr (std::is_same()){ put_in(static_cast(val.size()), vec); vec.insert(vec.end(), val.begin(), val.end()); } else{ static_assert(std::is_trivially_copyable() || std::is_same(), "Cannot serialize vectors of non-trivally copyable types" ", except vectors of std::string."); put_in(static_cast(val.size()), vec); for (const auto& el : val) put_in(el, vec); } } /** * This function extracts a variable of type T from a byte vector, at the position * given by a std::vector iterator. The iterator is then advanced according to * the number of bytes read from the byte vector. T must be either a trivially copyable type * or an std::string. * * @tparam T the variable type (must be trivially copyable) * @param[in, out] it the iterator to a byte vector * @return the variable extracted from the byte array */ template T get_out(std::vector::const_iterator& it) { if constexpr (std::is_same()){ const auto length = get_out (it); const auto str = std::string{it, it+length}; it += length; return str; } else{ static_assert(std::is_trivially_copyable(), "Cannot extract non-trivally copyable types from char vectors," " with the exception of std::string."); auto temp = std::array{}; std::copy(it, it + sizeof(T), temp.begin()); it += sizeof(T); T res; std::memcpy(&res, temp.data(), sizeof(T)); return res; } } /** * This function extracts an std::vector from a byte vector, at the position * given by a std::vector iterator. The iterator is then advanced according to * the number of bytes read from the byte vector. T must be either a trivially copyable type * or an std::string. * * @tparam T the variable type (must be trivially copyable) * @param[in, out] it the iterator to a byte vector * @return the variable extracted from the byte array */ template inline std::vector get_out_vec (std::vector::const_iterator& it) { if constexpr (std::is_same()){ const auto length = get_out (it); std::vector res(length); std::copy(it, it+length, res.begin()); it += length; return res; } else { static_assert(std::is_trivially_copyable() || std::is_same(), "Cannot extract non-trivally copyable types from char vectors," " with the exception of std::string."); const auto length = get_out (it); std::vector res(length); for (int i = 0; i < length; ++i) res[i] = get_out(it); return res; } } } } #endif //WARPX_MSG_LOGGER_SERIALIZATION_H_