// Copyright 2013 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_INTERNAL_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_

#include <new>
#include <string>
#include <type_traits>
#include <vector>

#include "mojo/public/c/system/macros.h"
#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
#include "mojo/public/cpp/bindings/lib/buffer.h"
#include "mojo/public/cpp/bindings/lib/map_data_internal.h"
#include "mojo/public/cpp/bindings/lib/validate_params.h"
#include "mojo/public/cpp/bindings/lib/validation_errors.h"
#include "mojo/public/cpp/environment/logging.h"

namespace mojo {
template <typename T>
class Array;
class String;

namespace internal {

// std::numeric_limits<uint32_t>::max() is not a compile-time constant (until
// C++11).
const uint32_t kMaxUint32 = 0xFFFFFFFF;

// TODO(vardhan): Get rid of the following 2 functions.
std::string MakeMessageWithArrayIndex(const char* message,
                                      size_t size,
                                      size_t index);

std::string MakeMessageWithExpectedArraySize(const char* message,
                                             size_t size,
                                             size_t expected_size);

template <typename T>
struct ArrayDataTraits {
  typedef T StorageType;
  typedef T& Ref;
  typedef T const& ConstRef;

  static const uint32_t kMaxNumElements =
      (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);

  static uint32_t GetStorageSize(uint32_t num_elements) {
    MOJO_DCHECK(num_elements <= kMaxNumElements);
    return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
  }
  static Ref ToRef(StorageType* storage, size_t offset) {
    return storage[offset];
  }
  static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
    return storage[offset];
  }
};

template <typename P, bool is_union>
struct ObjectStorageType;

template <typename P>
struct ObjectStorageType<P, true> {
  typedef P Type;
};

template <typename P>
struct ObjectStorageType<P, false> {
  typedef StructPointer<P> Type;
};

template <typename P>
struct ArrayDataTraits<P*> {
  typedef typename ObjectStorageType<P, IsUnionDataType<P>::value>::Type
      StorageType;
  typedef P*& Ref;
  typedef P* const& ConstRef;

  static const uint32_t kMaxNumElements =
      (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);

  static uint32_t GetStorageSize(uint32_t num_elements) {
    MOJO_DCHECK(num_elements <= kMaxNumElements);
    return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
  }
  static Ref ToRef(StorageType* storage, size_t offset) {
    return storage[offset].ptr;
  }
  static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
    return storage[offset].ptr;
  }
};

template <typename T>
struct ArrayDataTraits<Array_Data<T>*> {
  typedef ArrayPointer<T> StorageType;
  typedef Array_Data<T>*& Ref;
  typedef Array_Data<T>* const& ConstRef;

  static const uint32_t kMaxNumElements =
      (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);

  static uint32_t GetStorageSize(uint32_t num_elements) {
    MOJO_DCHECK(num_elements <= kMaxNumElements);
    return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
  }
  static Ref ToRef(StorageType* storage, size_t offset) {
    return storage[offset].ptr;
  }
  static ConstRef ToConstRef(const StorageType* storage, size_t offset) {
    return storage[offset].ptr;
  }
};

// Specialization of Arrays for bools, optimized for space. It has the
// following differences from a generalized Array:
// * Each element takes up a single bit of memory.
// * Accessing a non-const single element uses a helper class |BitRef|, which
// emulates a reference to a bool.
template <>
struct ArrayDataTraits<bool> {
  // Helper class to emulate a reference to a bool, used for direct element
  // access.
  class BitRef {
   public:
    ~BitRef();
    BitRef& operator=(bool value);
    BitRef& operator=(const BitRef& value);
    operator bool() const;

   private:
    friend struct ArrayDataTraits<bool>;
    BitRef(uint8_t* storage, uint8_t mask);
    BitRef();
    uint8_t* storage_;
    uint8_t mask_;
  };

  // Because each element consumes only 1/8 byte.
  static const uint32_t kMaxNumElements = kMaxUint32;

  typedef uint8_t StorageType;
  typedef BitRef Ref;
  typedef bool ConstRef;

  static uint32_t GetStorageSize(uint32_t num_elements) {
    return sizeof(ArrayHeader) + ((num_elements + 7) / 8);
  }
  static BitRef ToRef(StorageType* storage, size_t offset) {
    return BitRef(&storage[offset / 8], 1 << (offset % 8));
  }
  static bool ToConstRef(const StorageType* storage, size_t offset) {
    return (storage[offset / 8] & (1 << (offset % 8))) != 0;
  }
};

// What follows is code to support the serialization of Array_Data<T>. There
// are two interesting cases: arrays of primitives/unions, arrays of non-union
// objects (structs, arrays and maps).
// Arrays of non-union objects are represented as arrays of pointers to objects.
// Arrays of primitives or unions are represented as arrays of the values
// themselves.

template <typename T, bool is_handle, bool is_union>
struct ArraySerializationHelper;

template <typename T>
struct ArraySerializationHelper<T, false, false> {
  typedef typename ArrayDataTraits<T>::StorageType ElementType;

  static void EncodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {}

  static void DecodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {}

  static ValidationError ValidateElements(
      const ArrayHeader* header,
      const ElementType* elements,
      BoundsChecker* bounds_checker,
      const ArrayValidateParams* validate_params,
      std::string* err) {
    MOJO_DCHECK(!validate_params->element_is_nullable)
        << "Primitive type should be non-nullable";
    MOJO_DCHECK(!validate_params->element_validate_params)
        << "Primitive type should not have array validate params";
    return ValidationError::NONE;
  }
};

template <>
struct ArraySerializationHelper<Handle, true, false> {
  typedef ArrayDataTraits<Handle>::StorageType ElementType;

  static void EncodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles);

  static void DecodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles);

  static ValidationError ValidateElements(
      const ArrayHeader* header,
      const ElementType* elements,
      BoundsChecker* bounds_checker,
      const ArrayValidateParams* validate_params,
      std::string* err) {
    MOJO_DCHECK(!validate_params->element_validate_params)
        << "Handle type should not have array validate params";

    for (uint32_t i = 0; i < header->num_elements; ++i) {
      if (!validate_params->element_is_nullable &&
          elements[i].value() == kEncodedInvalidHandleValue) {
        MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
            << "invalid handle in array expecting valid handles (array size="
            << header->num_elements << ", index = " << i << ")";
        return ValidationError::UNEXPECTED_INVALID_HANDLE;
      }
      if (!bounds_checker->ClaimHandle(elements[i])) {
        MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
        return ValidationError::ILLEGAL_HANDLE;
      }
    }
    return ValidationError::NONE;
  }
};

template <typename H>
struct ArraySerializationHelper<H, true, false> {
  typedef typename ArrayDataTraits<H>::StorageType ElementType;

  static void EncodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {
    ArraySerializationHelper<Handle, true, false>::EncodePointersAndHandles(
        header, elements, handles);
  }

  static void DecodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {
    ArraySerializationHelper<Handle, true, false>::DecodePointersAndHandles(
        header, elements, handles);
  }

  static ValidationError ValidateElements(
      const ArrayHeader* header,
      const ElementType* elements,
      BoundsChecker* bounds_checker,
      const ArrayValidateParams* validate_params,
      std::string* err) {
    return ArraySerializationHelper<Handle, true, false>::ValidateElements(
        header, elements, bounds_checker, validate_params, err);
  }
};

template <typename P>
struct ArraySerializationHelper<P*, false, false> {
  typedef typename ArrayDataTraits<P*>::StorageType ElementType;

  static void EncodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {
    for (uint32_t i = 0; i < header->num_elements; ++i)
      Encode(&elements[i], handles);
  }

  static void DecodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {
    for (uint32_t i = 0; i < header->num_elements; ++i)
      Decode(&elements[i], handles);
  }

  static ValidationError ValidateElements(
      const ArrayHeader* header,
      const ElementType* elements,
      BoundsChecker* bounds_checker,
      const ArrayValidateParams* validate_params,
      std::string* err) {
    for (uint32_t i = 0; i < header->num_elements; ++i) {
      if (!validate_params->element_is_nullable && !elements[i].offset) {
        MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
            << "null in array expecting valid pointers (size="
            << header->num_elements << ", index = " << i << ")";
        return ValidationError::UNEXPECTED_NULL_POINTER;
      }

      if (!ValidateEncodedPointer(&elements[i].offset)) {
        MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
        return ValidationError::ILLEGAL_POINTER;
      }

      auto retval = ValidateCaller<P>::Run(
          DecodePointerRaw(&elements[i].offset), bounds_checker,
          validate_params->element_validate_params, err);
      if (retval != ValidationError::NONE)
        return retval;
    }
    return ValidationError::NONE;
  }

 private:
  template <typename T>
  struct ValidateCaller {
    static ValidationError Run(const void* data,
                               BoundsChecker* bounds_checker,
                               const ArrayValidateParams* validate_params,
                               std::string* err) {
      MOJO_DCHECK(!validate_params)
          << "Struct type should not have array validate params";

      return T::Validate(data, bounds_checker, err);
    }
  };

  template <typename Key, typename Value>
  struct ValidateCaller<Map_Data<Key, Value>> {
    static ValidationError Run(const void* data,
                               BoundsChecker* bounds_checker,
                               const ArrayValidateParams* validate_params,
                               std::string* err) {
      return Map_Data<Key, Value>::Validate(data, bounds_checker,
                                            validate_params, err);
    }
  };

  template <typename T>
  struct ValidateCaller<Array_Data<T>> {
    static ValidationError Run(const void* data,
                               BoundsChecker* bounds_checker,
                               const ArrayValidateParams* validate_params,
                               std::string* err) {
      return Array_Data<T>::Validate(data, bounds_checker, validate_params,
                                     err);
    }
  };
};

// Array Serialization Helper for unions.
template <typename P>
struct ArraySerializationHelper<P, false, true> {
  typedef P ElementType;

  static void EncodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {
    for (uint32_t i = 0; i < header->num_elements; ++i)
      elements[i].EncodePointersAndHandles(handles);
  }

  static void DecodePointersAndHandles(const ArrayHeader* header,
                                       ElementType* elements,
                                       std::vector<Handle>* handles) {
    for (uint32_t i = 0; i < header->num_elements; ++i)
      elements[i].DecodePointersAndHandles(handles);
  }

  static ValidationError ValidateElements(
      const ArrayHeader* header,
      const ElementType* elements,
      BoundsChecker* bounds_checker,
      const ArrayValidateParams* validate_params,
      std::string* err) {
    MOJO_DCHECK(!validate_params->element_validate_params)
        << "Union type should not have array validate params";
    for (uint32_t i = 0; i < header->num_elements; ++i) {
      if (!validate_params->element_is_nullable && elements[i].is_null()) {
        MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
            << "null union in array expecting non-null unions (size="
            << header->num_elements << ", index = " << i << ")";
        return ValidationError::UNEXPECTED_NULL_UNION;
      }

      auto retval = ElementType::Validate(
          static_cast<const void*>(&elements[i]), bounds_checker, true, err);
      if (retval != ValidationError::NONE)
        return retval;
    }
    return ValidationError::NONE;
  }
};

template <typename T>
class Array_Data {
 public:
  typedef ArrayDataTraits<T> Traits;
  typedef typename Traits::StorageType StorageType;
  typedef typename Traits::Ref Ref;
  typedef typename Traits::ConstRef ConstRef;
  typedef ArraySerializationHelper<
      T,
      IsHandle<T>::value,
      IsUnionDataType<typename std::remove_pointer<T>::type>::value> Helper;

  // Returns null if |num_elements| or the corresponding storage size cannot be
  // stored in uint32_t.
  static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
    if (num_elements > Traits::kMaxNumElements)
      return nullptr;

    uint32_t num_bytes =
        Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
    return new (buf->Allocate(num_bytes))
        Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements));
  }

  static ValidationError Validate(const void* data,
                                  BoundsChecker* bounds_checker,
                                  const ArrayValidateParams* validate_params,
                                  std::string* err) {
    if (!data)
      return ValidationError::NONE;
    if (!IsAligned(data)) {
      MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
      return ValidationError::MISALIGNED_OBJECT;
    }
    if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) {
      MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
      return ValidationError::ILLEGAL_MEMORY_RANGE;
    }

    const ArrayHeader* header = static_cast<const ArrayHeader*>(data);
    if (header->num_elements > Traits::kMaxNumElements ||
        header->num_bytes < Traits::GetStorageSize(header->num_elements)) {
      MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
      return ValidationError::UNEXPECTED_ARRAY_HEADER;
    }

    if (validate_params->expected_num_elements != 0 &&
        header->num_elements != validate_params->expected_num_elements) {
      MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err)
          << "fixed-size array has wrong number of elements (size="
          << header->num_elements
          << ", expected size=" << validate_params->expected_num_elements
          << ")";
      return ValidationError::UNEXPECTED_ARRAY_HEADER;
    }

    if (!bounds_checker->ClaimMemory(data, header->num_bytes)) {
      MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) << "";
      return ValidationError::ILLEGAL_MEMORY_RANGE;
    }

    const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data);
    return Helper::ValidateElements(&object->header_, object->storage(),
                                    bounds_checker, validate_params, err);
  }

  size_t size() const { return header_.num_elements; }

  Ref at(size_t offset) {
    MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements));
    return Traits::ToRef(storage(), offset);
  }

  ConstRef at(size_t offset) const {
    MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements));
    return Traits::ToConstRef(storage(), offset);
  }

  StorageType* storage() {
    return reinterpret_cast<StorageType*>(reinterpret_cast<char*>(this) +
                                          sizeof(*this));
  }

  const StorageType* storage() const {
    return reinterpret_cast<const StorageType*>(
        reinterpret_cast<const char*>(this) + sizeof(*this));
  }

  void EncodePointersAndHandles(std::vector<Handle>* handles) {
    Helper::EncodePointersAndHandles(&header_, storage(), handles);
  }

  void DecodePointersAndHandles(std::vector<Handle>* handles) {
    Helper::DecodePointersAndHandles(&header_, storage(), handles);
  }

 private:
  Array_Data(uint32_t num_bytes, uint32_t num_elements) {
    header_.num_bytes = num_bytes;
    header_.num_elements = num_elements;
  }
  ~Array_Data() = delete;

  internal::ArrayHeader header_;

  // Elements of type internal::ArrayDataTraits<T>::StorageType follow.
};
static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)");

// UTF-8 encoded
typedef Array_Data<char> String_Data;

template <typename T, bool kIsMoveOnlyType>
struct ArrayTraits {};

template <typename T>
struct ArrayTraits<T, false> {
  typedef typename std::vector<T>::const_reference ForwardType;
  static inline void PushBack(std::vector<T>* vec, ForwardType value) {
    vec->push_back(value);
  }
  static inline void Clone(const std::vector<T>& src_vec,
                           std::vector<T>* dest_vec) {
    dest_vec->assign(src_vec.begin(), src_vec.end());
  }
};

template <typename T>
struct ArrayTraits<T, true> {
  typedef T ForwardType;
  static inline void PushBack(std::vector<T>* vec, T& value) {
    vec->push_back(value.Pass());
  }
  static inline void Clone(const std::vector<T>& src_vec,
                           std::vector<T>* dest_vec) {
    dest_vec->resize(src_vec.size());
    for (size_t i = 0; i < src_vec.size(); ++i)
      dest_vec->at(i) = src_vec.at(i).Clone();
  }
};

template <>
struct WrapperTraits<String, false> {
  typedef String_Data* DataType;
};

}  // namespace internal
}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
