#ifndef EIGEN_SERIALIZER_H
#define EIGEN_SERIALIZER_H
#include <type_traits>
namespace Eigen {
template <typename T, typename EnableIf = void>
class Serializer;
template <typename T>
class Serializer<T,
typename std::enable_if_t<std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value>> {
public:
EIGEN_DEVICE_FUNC size_t size(const T& value) const { return sizeof(value); }
EIGEN_DEVICE_FUNC uint8_t* serialize(uint8_t* dest, uint8_t* end, const T& value) {
if (EIGEN_PREDICT_FALSE(dest == nullptr)) return nullptr;
if (EIGEN_PREDICT_FALSE(dest + sizeof(value) > end)) return nullptr;
EIGEN_USING_STD(memcpy)
memcpy(dest, &value, sizeof(value));
return dest + sizeof(value);
}
EIGEN_DEVICE_FUNC const uint8_t* deserialize(const uint8_t* src, const uint8_t* end, T& value) const {
if (EIGEN_PREDICT_FALSE(src == nullptr)) return nullptr;
if (EIGEN_PREDICT_FALSE(src + sizeof(value) > end)) return nullptr;
EIGEN_USING_STD(memcpy)
memcpy(&value, src, sizeof(value));
return src + sizeof(value);
}
};
template <typename Derived>
class Serializer<DenseBase<Derived>, void> {
public:
typedef typename Derived::Scalar Scalar;
struct Header {
typename Derived::Index rows;
typename Derived::Index cols;
};
EIGEN_DEVICE_FUNC size_t size(const Derived& value) const { return sizeof(Header) + sizeof(Scalar) * value.size(); }
EIGEN_DEVICE_FUNC uint8_t* serialize(uint8_t* dest, uint8_t* end, const Derived& value) {
if (EIGEN_PREDICT_FALSE(dest == nullptr)) return nullptr;
if (EIGEN_PREDICT_FALSE(dest + size(value) > end)) return nullptr;
const size_t header_bytes = sizeof(Header);
const size_t data_bytes = sizeof(Scalar) * value.size();
Header header = {value.rows(), value.cols()};
EIGEN_USING_STD(memcpy)
memcpy(dest, &header, header_bytes);
dest += header_bytes;
memcpy(dest, value.data(), data_bytes);
return dest + data_bytes;
}
EIGEN_DEVICE_FUNC const uint8_t* deserialize(const uint8_t* src, const uint8_t* end, Derived& value) const {
if (EIGEN_PREDICT_FALSE(src == nullptr)) return nullptr;
if (EIGEN_PREDICT_FALSE(src + sizeof(Header) > end)) return nullptr;
const size_t header_bytes = sizeof(Header);
Header header;
EIGEN_USING_STD(memcpy)
memcpy(&header, src, header_bytes);
src += header_bytes;
const size_t data_bytes = sizeof(Scalar) * header.rows * header.cols;
if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
value.resize(header.rows, header.cols);
memcpy(value.data(), src, data_bytes);
return src + data_bytes;
}
};
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
class Serializer<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
: public Serializer<DenseBase<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>> {};
template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
class Serializer<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>
: public Serializer<DenseBase<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>>> {};
namespace internal {
template <size_t N, typename... Types>
struct serialize_impl;
template <size_t N, typename T1, typename... Ts>
struct serialize_impl<N, T1, Ts...> {
using Serializer = Eigen::Serializer<typename std::decay<T1>::type>;
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size(const T1& value, const Ts&... args) {
Serializer serializer;
size_t size = serializer.size(value);
return size + serialize_impl<N - 1, Ts...>::serialize_size(args...);
}
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t* end, const T1& value,
const Ts&... args) {
Serializer serializer;
dest = serializer.serialize(dest, end, value);
return serialize_impl<N - 1, Ts...>::serialize(dest, end, args...);
}
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* end,
T1& value, Ts&... args) {
Serializer serializer;
src = serializer.deserialize(src, end, value);
return serialize_impl<N - 1, Ts...>::deserialize(src, end, args...);
}
};
template <>
struct serialize_impl<0> {
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size() { return 0; }
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t* ) { return dest; }
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* ) {
return src;
}
};
}
template <typename... Args>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t serialize_size(const Args&... args) {
return internal::serialize_impl<sizeof...(args), Args...>::serialize_size(args...);
}
template <typename... Args>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint8_t* serialize(uint8_t* dest, uint8_t* end, const Args&... args) {
return internal::serialize_impl<sizeof...(args), Args...>::serialize(dest, end, args...);
}
template <typename... Args>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* end,
Args&... args) {
return internal::serialize_impl<sizeof...(args), Args...>::deserialize(src, end, args...);
}
}
#endif