// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_

#include <stddef.h>
#include <string.h>  // For |memcpy()|.

#include <limits>
#include <type_traits>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "mojo/public/cpp/bindings/array_data_view.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/lib/validation_errors.h"

namespace mojo {
namespace internal {

template <typename Traits,
          typename MaybeConstUserType,
          bool HasGetBegin =
              HasGetBeginMethod<Traits, MaybeConstUserType>::value>
class ArrayIterator {};

// Used as the UserTypeIterator template parameter of ArraySerializer.
template <typename Traits, typename MaybeConstUserType>
class ArrayIterator<Traits, MaybeConstUserType, true> {
 public:
  using IteratorType = decltype(
      CallGetBeginIfExists<Traits>(std::declval<MaybeConstUserType&>()));

  explicit ArrayIterator(MaybeConstUserType& input)
      : input_(input), iter_(CallGetBeginIfExists<Traits>(input)) {}
  ~ArrayIterator() {}

  size_t GetSize() const { return Traits::GetSize(input_); }

  using GetNextResult =
      decltype(Traits::GetValue(std::declval<IteratorType&>()));
  GetNextResult GetNext() {
    GetNextResult value = Traits::GetValue(iter_);
    Traits::AdvanceIterator(iter_);
    return value;
  }

  using GetDataIfExistsResult = decltype(
      CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>()));
  GetDataIfExistsResult GetDataIfExists() {
    return CallGetDataIfExists<Traits>(input_);
  }

 private:
  MaybeConstUserType& input_;
  IteratorType iter_;
};

// Used as the UserTypeIterator template parameter of ArraySerializer.
template <typename Traits, typename MaybeConstUserType>
class ArrayIterator<Traits, MaybeConstUserType, false> {
 public:
  explicit ArrayIterator(MaybeConstUserType& input) : input_(input), iter_(0) {}
  ~ArrayIterator() {}

  size_t GetSize() const { return Traits::GetSize(input_); }

  using GetNextResult =
      decltype(Traits::GetAt(std::declval<MaybeConstUserType&>(), 0));
  GetNextResult GetNext() {
    DCHECK_LT(iter_, Traits::GetSize(input_));
    return Traits::GetAt(input_, iter_++);
  }

  using GetDataIfExistsResult = decltype(
      CallGetDataIfExists<Traits>(std::declval<MaybeConstUserType&>()));
  GetDataIfExistsResult GetDataIfExists() {
    return CallGetDataIfExists<Traits>(input_);
  }

 private:
  MaybeConstUserType& input_;
  size_t iter_;
};

// ArraySerializer is also used to serialize map keys and values. Therefore, it
// has a UserTypeIterator parameter which is an adaptor for reading to hide the
// difference between ArrayTraits and MapTraits.
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator,
          typename EnableType = void>
struct ArraySerializer;

// Handles serialization and deserialization of arrays of pod types.
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator>
struct ArraySerializer<
    MojomType,
    MaybeConstUserType,
    UserTypeIterator,
    typename std::enable_if<BelongsTo<typename MojomType::Element,
                                      MojomTypeCategory::POD>::value>::type> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Data = typename MojomTypeTraits<MojomType>::Data;
  using DataElement = typename Data::Element;
  using Element = typename MojomType::Element;
  using Traits = ArrayTraits<UserType>;
  using BufferWriter = typename Data::BufferWriter;

  static_assert(std::is_same<Element, DataElement>::value,
                "Incorrect array serializer");
  static_assert(
      std::is_same<
          Element,
          typename std::remove_const<typename Traits::Element>::type>::value,
      "Incorrect array serializer");

  static void SerializeElements(UserTypeIterator* input,
                                Buffer* buf,
                                BufferWriter* writer,
                                const ContainerValidateParams* validate_params,
                                SerializationContext* context) {
    DCHECK(!validate_params->element_is_nullable)
        << "Primitive type should be non-nullable";
    DCHECK(!validate_params->element_validate_params)
        << "Primitive type should not have array validate params";

    size_t size = input->GetSize();
    if (size == 0)
      return;

    auto data = input->GetDataIfExists();
    Data* output = writer->data();
    if (data) {
      memcpy(output->storage(), data, size * sizeof(DataElement));
    } else {
      for (size_t i = 0; i < size; ++i)
        output->at(i) = input->GetNext();
    }
  }

  static bool DeserializeElements(Data* input,
                                  UserType* output,
                                  SerializationContext* context) {
    if (!Traits::Resize(*output, input->size()))
      return false;
    ArrayIterator<Traits, UserType> iterator(*output);
    if (input->size()) {
      auto data = iterator.GetDataIfExists();
      if (data) {
        memcpy(data, input->storage(), input->size() * sizeof(DataElement));
      } else {
        for (size_t i = 0; i < input->size(); ++i)
          iterator.GetNext() = input->at(i);
      }
    }
    return true;
  }
};

// Handles serialization and deserialization of arrays of enum types.
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator>
struct ArraySerializer<
    MojomType,
    MaybeConstUserType,
    UserTypeIterator,
    typename std::enable_if<BelongsTo<typename MojomType::Element,
                                      MojomTypeCategory::ENUM>::value>::type> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Data = typename MojomTypeTraits<MojomType>::Data;
  using DataElement = typename Data::Element;
  using Element = typename MojomType::Element;
  using Traits = ArrayTraits<UserType>;
  using BufferWriter = typename Data::BufferWriter;

  static_assert(sizeof(Element) == sizeof(DataElement),
                "Incorrect array serializer");

  static void SerializeElements(UserTypeIterator* input,
                                Buffer* buf,
                                BufferWriter* writer,
                                const ContainerValidateParams* validate_params,
                                SerializationContext* context) {
    DCHECK(!validate_params->element_is_nullable)
        << "Primitive type should be non-nullable";
    DCHECK(!validate_params->element_validate_params)
        << "Primitive type should not have array validate params";

    Data* output = writer->data();
    size_t size = input->GetSize();
    for (size_t i = 0; i < size; ++i)
      Serialize<Element>(input->GetNext(), output->storage() + i);
  }

  static bool DeserializeElements(Data* input,
                                  UserType* output,
                                  SerializationContext* context) {
    if (!Traits::Resize(*output, input->size()))
      return false;
    ArrayIterator<Traits, UserType> iterator(*output);
    for (size_t i = 0; i < input->size(); ++i) {
      if (!Deserialize<Element>(input->at(i), &iterator.GetNext()))
        return false;
    }
    return true;
  }
};

// Serializes and deserializes arrays of bools.
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator>
struct ArraySerializer<MojomType,
                       MaybeConstUserType,
                       UserTypeIterator,
                       typename std::enable_if<BelongsTo<
                           typename MojomType::Element,
                           MojomTypeCategory::BOOLEAN>::value>::type> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Traits = ArrayTraits<UserType>;
  using Data = typename MojomTypeTraits<MojomType>::Data;
  using BufferWriter = typename Data::BufferWriter;

  static_assert(std::is_same<bool, typename Traits::Element>::value,
                "Incorrect array serializer");

  static void SerializeElements(UserTypeIterator* input,
                                Buffer* buf,
                                BufferWriter* writer,
                                const ContainerValidateParams* validate_params,
                                SerializationContext* context) {
    DCHECK(!validate_params->element_is_nullable)
        << "Primitive type should be non-nullable";
    DCHECK(!validate_params->element_validate_params)
        << "Primitive type should not have array validate params";

    Data* output = writer->data();
    size_t size = input->GetSize();
    for (size_t i = 0; i < size; ++i)
      output->at(i) = input->GetNext();
  }
  static bool DeserializeElements(Data* input,
                                  UserType* output,
                                  SerializationContext* context) {
    if (!Traits::Resize(*output, input->size()))
      return false;
    ArrayIterator<Traits, UserType> iterator(*output);
    for (size_t i = 0; i < input->size(); ++i)
      iterator.GetNext() = input->at(i);
    return true;
  }
};

// Serializes and deserializes arrays of handles or interfaces.
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator>
struct ArraySerializer<
    MojomType,
    MaybeConstUserType,
    UserTypeIterator,
    typename std::enable_if<
        BelongsTo<typename MojomType::Element,
                  MojomTypeCategory::ASSOCIATED_INTERFACE |
                      MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST |
                      MojomTypeCategory::HANDLE | MojomTypeCategory::INTERFACE |
                      MojomTypeCategory::INTERFACE_REQUEST>::value>::type> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Data = typename MojomTypeTraits<MojomType>::Data;
  using Element = typename MojomType::Element;
  using Traits = ArrayTraits<UserType>;
  using BufferWriter = typename Data::BufferWriter;

  static void SerializeElements(UserTypeIterator* input,
                                Buffer* buf,
                                BufferWriter* writer,
                                const ContainerValidateParams* validate_params,
                                SerializationContext* context) {
    DCHECK(!validate_params->element_validate_params)
        << "Handle or interface type should not have array validate params";

    Data* output = writer->data();
    size_t size = input->GetSize();
    for (size_t i = 0; i < size; ++i) {
      typename UserTypeIterator::GetNextResult next = input->GetNext();
      Serialize<Element>(next, &output->at(i), context);

      static const ValidationError kError =
          BelongsTo<Element,
                    MojomTypeCategory::ASSOCIATED_INTERFACE |
                        MojomTypeCategory::ASSOCIATED_INTERFACE_REQUEST>::value
              ? VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID
              : VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE;
      MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
          !validate_params->element_is_nullable &&
              !IsHandleOrInterfaceValid(output->at(i)),
          kError,
          MakeMessageWithArrayIndex("invalid handle or interface ID in array "
                                    "expecting valid handles or interface IDs",
                                    size, i));
    }
  }
  static bool DeserializeElements(Data* input,
                                  UserType* output,
                                  SerializationContext* context) {
    if (!Traits::Resize(*output, input->size()))
      return false;
    ArrayIterator<Traits, UserType> iterator(*output);
    for (size_t i = 0; i < input->size(); ++i) {
      bool result =
          Deserialize<Element>(&input->at(i), &iterator.GetNext(), context);
      DCHECK(result);
    }
    return true;
  }
};

// This template must only apply to pointer mojo entity (strings, structs,
// arrays and maps).
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator>
struct ArraySerializer<MojomType,
                       MaybeConstUserType,
                       UserTypeIterator,
                       typename std::enable_if<BelongsTo<
                           typename MojomType::Element,
                           MojomTypeCategory::ARRAY | MojomTypeCategory::MAP |
                               MojomTypeCategory::STRING |
                               MojomTypeCategory::STRUCT>::value>::type> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Data = typename MojomTypeTraits<MojomType>::Data;
  using Element = typename MojomType::Element;
  using DataElementWriter =
      typename MojomTypeTraits<Element>::Data::BufferWriter;
  using Traits = ArrayTraits<UserType>;
  using BufferWriter = typename Data::BufferWriter;

  static void SerializeElements(UserTypeIterator* input,
                                Buffer* buf,
                                BufferWriter* writer,
                                const ContainerValidateParams* validate_params,
                                SerializationContext* context) {
    size_t size = input->GetSize();
    for (size_t i = 0; i < size; ++i) {
      DataElementWriter data_writer;
      typename UserTypeIterator::GetNextResult next = input->GetNext();
      SerializeCaller<Element>::Run(next, buf, &data_writer,
                                    validate_params->element_validate_params,
                                    context);
      writer->data()->at(i).Set(data_writer.is_null() ? nullptr
                                                      : data_writer.data());
      MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
          !validate_params->element_is_nullable && data_writer.is_null(),
          VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
          MakeMessageWithArrayIndex("null in array expecting valid pointers",
                                    size, i));
    }
  }
  static bool DeserializeElements(Data* input,
                                  UserType* output,
                                  SerializationContext* context) {
    if (!Traits::Resize(*output, input->size()))
      return false;
    ArrayIterator<Traits, UserType> iterator(*output);
    for (size_t i = 0; i < input->size(); ++i) {
      if (!Deserialize<Element>(input->at(i).Get(), &iterator.GetNext(),
                                context))
        return false;
    }
    return true;
  }

 private:
  template <typename T,
            bool is_array_or_map = BelongsTo<T,
                                             MojomTypeCategory::ARRAY |
                                                 MojomTypeCategory::MAP>::value>
  struct SerializeCaller {
    template <typename InputElementType>
    static void Run(InputElementType&& input,
                    Buffer* buf,
                    DataElementWriter* writer,
                    const ContainerValidateParams* validate_params,
                    SerializationContext* context) {
      Serialize<T>(std::forward<InputElementType>(input), buf, writer, context);
    }
  };

  template <typename T>
  struct SerializeCaller<T, true> {
    template <typename InputElementType>
    static void Run(InputElementType&& input,
                    Buffer* buf,
                    DataElementWriter* writer,
                    const ContainerValidateParams* validate_params,
                    SerializationContext* context) {
      Serialize<T>(std::forward<InputElementType>(input), buf, writer,
                   validate_params, context);
    }
  };
};

// Handles serialization and deserialization of arrays of unions.
template <typename MojomType,
          typename MaybeConstUserType,
          typename UserTypeIterator>
struct ArraySerializer<
    MojomType,
    MaybeConstUserType,
    UserTypeIterator,
    typename std::enable_if<BelongsTo<typename MojomType::Element,
                                      MojomTypeCategory::UNION>::value>::type> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Data = typename MojomTypeTraits<MojomType>::Data;
  using Element = typename MojomType::Element;
  using ElementWriter = typename Data::Element::BufferWriter;
  using Traits = ArrayTraits<UserType>;
  using BufferWriter = typename Data::BufferWriter;

  static void SerializeElements(UserTypeIterator* input,
                                Buffer* buf,
                                BufferWriter* writer,
                                const ContainerValidateParams* validate_params,
                                SerializationContext* context) {
    size_t size = input->GetSize();
    for (size_t i = 0; i < size; ++i) {
      ElementWriter result;
      result.AllocateInline(buf, writer->data()->storage() + i);
      typename UserTypeIterator::GetNextResult next = input->GetNext();
      Serialize<Element>(next, buf, &result, true, context);
      MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
          !validate_params->element_is_nullable &&
              writer->data()->at(i).is_null(),
          VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
          MakeMessageWithArrayIndex("null in array expecting valid unions",
                                    size, i));
    }
  }

  static bool DeserializeElements(Data* input,
                                  UserType* output,
                                  SerializationContext* context) {
    if (!Traits::Resize(*output, input->size()))
      return false;
    ArrayIterator<Traits, UserType> iterator(*output);
    for (size_t i = 0; i < input->size(); ++i) {
      if (!Deserialize<Element>(&input->at(i), &iterator.GetNext(), context))
        return false;
    }
    return true;
  }
};

template <typename Element, typename MaybeConstUserType>
struct Serializer<ArrayDataView<Element>, MaybeConstUserType> {
  using UserType = typename std::remove_const<MaybeConstUserType>::type;
  using Traits = ArrayTraits<UserType>;
  using Impl = ArraySerializer<ArrayDataView<Element>,
                               MaybeConstUserType,
                               ArrayIterator<Traits, MaybeConstUserType>>;
  using Data = typename MojomTypeTraits<ArrayDataView<Element>>::Data;
  using BufferWriter = typename Data::BufferWriter;

  static void Serialize(MaybeConstUserType& input,
                        Buffer* buf,
                        BufferWriter* writer,
                        const ContainerValidateParams* validate_params,
                        SerializationContext* context) {
    if (CallIsNullIfExists<Traits>(input))
      return;

    const size_t size = Traits::GetSize(input);
    MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
        validate_params->expected_num_elements != 0 &&
            size != validate_params->expected_num_elements,
        internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
        internal::MakeMessageWithExpectedArraySize(
            "fixed-size array has wrong number of elements", size,
            validate_params->expected_num_elements));
    writer->Allocate(size, buf);
    ArrayIterator<Traits, MaybeConstUserType> iterator(input);
    Impl::SerializeElements(&iterator, buf, writer, validate_params, context);
  }

  static bool Deserialize(Data* input,
                          UserType* output,
                          SerializationContext* context) {
    if (!input)
      return CallSetToNullIfExists<Traits>(output);
    return Impl::DeserializeElements(input, output, context);
  }
};

}  // namespace internal
}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_SERIALIZATION_H_
