// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2021 The Eigen Team
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_SERIALIZER_H
#define EIGEN_SERIALIZER_H

#include <type_traits>

// The Serializer class encodes data into a memory buffer so it can be later
// reconstructed. This is mainly used to send objects back-and-forth between
// the CPU and GPU.

namespace Eigen {

/**
 * Serializes an object to a memory buffer.
 *
 * Useful for transferring data (e.g. back-and-forth to a device).
 */
template <typename T, typename EnableIf = void>
class Serializer;

// Specialization for POD types.
template <typename T>
class Serializer<T,
                 typename std::enable_if_t<std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value>> {
 public:
  /**
   * Determines the required size of the serialization buffer for a value.
   *
   * \param value the value to serialize.
   * \return the required size.
   */
  EIGEN_DEVICE_FUNC size_t size(const T& value) const { return sizeof(value); }

  /**
   * Serializes a value to a byte buffer.
   * \param dest the destination buffer; if this is nullptr, does nothing.
   * \param end the end of the destination buffer.
   * \param value the value to serialize.
   * \return the next memory address past the end of the serialized data.
   */
  EIGEN_DEVICE_FUNC uint8_t* serialize(uint8_t* dest, uint8_t* end, const T& value) const {
    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);
  }

  /**
   * Deserializes a value from a byte buffer.
   * \param src the source buffer; if this is nullptr, does nothing.
   * \param end the end of the source buffer.
   * \param value the value to populate.
   * \return the next unprocessed memory address; nullptr if parsing errors are detected.
   */
  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);
  }
};

// Specialization for DenseBase.
// Serializes [rows, cols, data...].
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) const {
    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 {

// Recursive serialization implementation helper.
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<std::decay_t<T1>>;

  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...);
  }
};

// Base case.
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* /*end*/) { return dest; }

  static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const uint8_t* deserialize(const uint8_t* src, const uint8_t* /*end*/) {
    return src;
  }
};

}  // namespace internal

/**
 * Determine the buffer size required to serialize a set of values.
 *
 * \param args ... arguments to serialize in sequence.
 * \return the total size of the required buffer.
 */
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...);
}

/**
 * Serialize a set of values to the byte buffer.
 *
 * \param dest output byte buffer; if this is nullptr, does nothing.
 * \param end the end of the output byte buffer.
 * \param args ... arguments to serialize in sequence.
 * \return the next address after all serialized values.
 */
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...);
}

/**
 * Deserialize a set of values from the byte buffer.
 *
 * \param src input byte buffer; if this is nullptr, does nothing.
 * \param end the end of input byte buffer.
 * \param args ... arguments to deserialize in sequence.
 * \return the next address after all parsed values; nullptr if parsing errors are detected.
 */
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...);
}

}  // namespace Eigen

#endif  // EIGEN_SERIALIZER_H
