// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

// This header defines the RepeatedFieldRef class template used to access
// repeated fields with protobuf reflection API.
#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
#define GOOGLE_PROTOBUF_REFLECTION_H__

#include <memory>
#include <type_traits>

#include "absl/base/attributes.h"
#include "google/protobuf/generated_enum_util.h"
#include "google/protobuf/descriptor.h"

#ifdef SWIG
#error "You cannot SWIG proto headers"
#endif

// Must be included last.
#include "google/protobuf/port_def.inc"

namespace google {
namespace protobuf {
namespace internal {
template <typename T, typename Enable = void>
struct RefTypeTraits;
}  // namespace internal

class Message;

template <typename Dep, typename T>
using MakeDependent = std::conditional_t<true, T, Dep>;

// Forward-declare RepeatedFieldRef templates. The second type parameter is
// used for SFINAE tricks. Users should ignore it.
template <typename T, typename Enable = void>
class RepeatedFieldRef;

template <typename T, typename Enable = void>
class MutableRepeatedFieldRef;

// RepeatedFieldRef definition for non-message types.
template <typename T>
class RepeatedFieldRef<
    T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
  typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;

 public:
  bool empty() const { return accessor_->IsEmpty(data_); }
  int size() const { return accessor_->Size(data_); }
  T Get(int index) const { return accessor_->template Get<T>(data_, index); }

  typedef IteratorType iterator;
  typedef IteratorType const_iterator;
  typedef T value_type;
  typedef T& reference;
  typedef const T& const_reference;
  typedef int size_type;
  typedef ptrdiff_t difference_type;

  iterator begin() const { return iterator(data_, accessor_, true); }
  iterator end() const { return iterator(data_, accessor_, false); }

 private:
  friend class Reflection;
  RepeatedFieldRef(const MakeDependent<T, Message>& message,
                   const FieldDescriptor* PROTOBUF_NONNULL field) {
    const auto* reflection = message.GetReflection();
    data_ = reflection->RepeatedFieldData(
        message, field, internal::RefTypeTraits<T>::cpp_type, nullptr);
    accessor_ = reflection->RepeatedFieldAccessor(field);
  }

  const void* PROTOBUF_NONNULL data_;
  const AccessorType* PROTOBUF_NONNULL accessor_;
};

// MutableRepeatedFieldRef definition for non-message types.
template <typename T>
class MutableRepeatedFieldRef<
    T, typename std::enable_if<!std::is_base_of<Message, T>::value>::type> {
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;

 public:
  bool empty() const { return accessor_->IsEmpty(data_); }
  int size() const { return accessor_->Size(data_); }
  T Get(int index) const { return accessor_->template Get<T>(data_, index); }

  void Set(int index, const T& value) const {
    accessor_->template Set<T>(data_, index, value);
  }
  void Add(const T& value) const { accessor_->template Add<T>(data_, value); }
  void RemoveLast() const { accessor_->RemoveLast(data_); }
  void SwapElements(int index1, int index2) const {
    accessor_->SwapElements(data_, index1, index2);
  }
  void Clear() const { accessor_->Clear(data_); }

  void Swap(const MutableRepeatedFieldRef& other) const {
    accessor_->Swap(data_, other.accessor_, other.data_);
  }

  template <typename Container>
  void MergeFrom(const Container& container) const {
    typedef typename Container::const_iterator Iterator;
    for (Iterator it = container.begin(); it != container.end(); ++it) {
      Add(*it);
    }
  }
  template <typename Container>
  void CopyFrom(const Container& container) const {
    Clear();
    MergeFrom(container);
  }

 private:
  friend class Reflection;
  MutableRepeatedFieldRef(MakeDependent<T, Message>* PROTOBUF_NONNULL message,
                          const FieldDescriptor* PROTOBUF_NONNULL field) {
    const auto* reflection = message->GetReflection();
    data_ = reflection->RepeatedFieldData(
        message, field, internal::RefTypeTraits<T>::cpp_type, nullptr);
    accessor_ = reflection->RepeatedFieldAccessor(field);
  }

  void* PROTOBUF_NONNULL data_;
  const AccessorType* PROTOBUF_NONNULL accessor_;
};

// RepeatedFieldRef definition for message types.
template <typename T>
class RepeatedFieldRef<
    T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
  typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;

 public:
  bool empty() const { return accessor_->IsEmpty(data_); }
  int size() const { return accessor_->Size(data_); }
  // This method returns a reference to the underlying message object if it
  // exists. If a message object doesn't exist (e.g., data stored in serialized
  // form), scratch_space will be filled with the data and a reference to it
  // will be returned.
  //
  // Example:
  //   RepeatedFieldRef<Message> h = ...
  //   unique_ptr<Message> scratch_space(h.NewMessage());
  //   const Message& item = h.Get(index, scratch_space.get());
  const T& Get(int index, T* PROTOBUF_NULLABLE scratch_space) const {
    return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
  }
  // Create a new message of the same type as the messages stored in this
  // repeated field. Caller takes ownership of the returned object.
  T* PROTOBUF_NONNULL NewMessage() const { return default_instance_->New(); }

  typedef IteratorType iterator;
  typedef IteratorType const_iterator;
  typedef T value_type;
  typedef T& reference;
  typedef const T& const_reference;
  typedef int size_type;
  typedef ptrdiff_t difference_type;

  iterator begin() const {
    return iterator(data_, accessor_, true, NewMessage());
  }
  iterator end() const {
    // The end iterator must not be dereferenced, no need for scratch space.
    return iterator(data_, accessor_, false, nullptr);
  }

 private:
  friend class Reflection;
  RepeatedFieldRef(const MakeDependent<T, Message>& message,
                   const FieldDescriptor* PROTOBUF_NONNULL field) {
    const auto* reflection = message.GetReflection();
    data_ = reflection->RepeatedFieldData(
        message, field, internal::RefTypeTraits<T>::cpp_type,
        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
    accessor_ = reflection->RepeatedFieldAccessor(field);
    default_instance_ = static_cast<const T*>(
        reflection->GetMessageFactory()->GetPrototype(field->message_type()));
  }

  const void* PROTOBUF_NONNULL data_;
  const AccessorType* PROTOBUF_NONNULL accessor_;
  const T* PROTOBUF_NONNULL default_instance_;
};

// MutableRepeatedFieldRef definition for message types.
template <typename T>
class MutableRepeatedFieldRef<
    T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
  typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;

 public:
  bool empty() const { return accessor_->IsEmpty(data_); }
  int size() const { return accessor_->Size(data_); }
  // See comments for RepeatedFieldRef<Message>::Get()
  const T& Get(int index, T* PROTOBUF_NULLABLE scratch_space) const {
    return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
  }
  // Create a new message of the same type as the messages stored in this
  // repeated field. Caller takes ownership of the returned object.
  T* PROTOBUF_NONNULL NewMessage() const { return default_instance_->New(); }

  void Set(int index, const T& value) const {
    accessor_->Set(data_, index, &value);
  }
  void Add(const T& value) const { accessor_->Add(data_, &value); }
  void RemoveLast() const { accessor_->RemoveLast(data_); }
  void SwapElements(int index1, int index2) const {
    accessor_->SwapElements(data_, index1, index2);
  }
  void Clear() const { accessor_->Clear(data_); }

  void Swap(const MutableRepeatedFieldRef& other) const {
    accessor_->Swap(data_, other.accessor_, other.data_);
  }

  template <typename Container>
  void MergeFrom(const Container& container) const {
    typedef typename Container::const_iterator Iterator;
    for (Iterator it = container.begin(); it != container.end(); ++it) {
      Add(*it);
    }
  }
  template <typename Container>
  void CopyFrom(const Container& container) const {
    Clear();
    MergeFrom(container);
  }

 private:
  friend class Reflection;
  MutableRepeatedFieldRef(MakeDependent<T, Message>* PROTOBUF_NONNULL message,
                          const FieldDescriptor* PROTOBUF_NONNULL field) {
    const auto* reflection = message->GetReflection();
    data_ = reflection->RepeatedFieldData(
        message, field, internal::RefTypeTraits<T>::cpp_type,
        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
    accessor_ = reflection->RepeatedFieldAccessor(field);
    default_instance_ = static_cast<const T*>(
        reflection->GetMessageFactory()->GetPrototype(field->message_type()));
  }

  void* PROTOBUF_NONNULL data_;
  const AccessorType* PROTOBUF_NONNULL accessor_;
  const T* PROTOBUF_NONNULL default_instance_;
};

namespace internal {
// Interfaces used to implement reflection RepeatedFieldRef API.
// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
// object that implements the below interface.
//
// This interface passes/returns values using void pointers. The actual type
// of the value depends on the field's cpp_type. Following is a mapping from
// cpp_type to the type that should be used in this interface:
//
//   field->cpp_type()      T                Actual type of void*
//   CPPTYPE_INT32        int32_t                 int32_t
//   CPPTYPE_UINT32       uint32_t                uint32_t
//   CPPTYPE_INT64        int64_t                 int64_t
//   CPPTYPE_UINT64       uint64_t                uint64_t
//   CPPTYPE_DOUBLE       double                  double
//   CPPTYPE_FLOAT        float                   float
//   CPPTYPE_BOOL         bool                    bool
//   CPPTYPE_ENUM         generated enum type     int32_t
//   CPPTYPE_STRING       string                  std::string
//   CPPTYPE_MESSAGE      generated message type  google::protobuf::Message
//                        or google::protobuf::Message
//
// Note that for enums we use int32_t in the interface.
//
// You can map from T to the actual type using RefTypeTraits:
//   typedef RefTypeTraits<T>::AccessorValueType ActualType;
class PROTOBUF_EXPORT RepeatedFieldAccessor {
 public:
  // Typedefs for clarity.
  typedef void Field;
  typedef void Value;
  typedef void Iterator;

  virtual bool IsEmpty(const Field* PROTOBUF_NONNULL data) const = 0;
  virtual int Size(const Field* PROTOBUF_NONNULL data) const = 0;
  // Depends on the underlying representation of the repeated field, this
  // method can return a pointer to the underlying object if such an object
  // exists, or fill the data into scratch_space and return scratch_space.
  // Callers of this method must ensure scratch_space is a valid pointer
  // to a mutable object of the correct type.
  virtual const Value* PROTOBUF_NONNULL
  Get(const Field* PROTOBUF_NONNULL data, int index,
      Value* PROTOBUF_NULLABLE scratch_space) const = 0;

  virtual void Clear(Field* PROTOBUF_NONNULL data) const = 0;
  virtual void Set(Field* PROTOBUF_NONNULL data, int index,
                   const Value* PROTOBUF_NONNULL value) const = 0;
  virtual void Add(Field* PROTOBUF_NONNULL data,
                   const Value* PROTOBUF_NONNULL value) const = 0;
  virtual void RemoveLast(Field* PROTOBUF_NONNULL data) const = 0;
  virtual void SwapElements(Field* PROTOBUF_NONNULL data, int index1,
                            int index2) const = 0;
  virtual void Swap(Field* PROTOBUF_NONNULL data,
                    const RepeatedFieldAccessor* PROTOBUF_NONNULL other_mutator,
                    Field* PROTOBUF_NONNULL other_data) const = 0;

  // Create an iterator that points at the beginning of the repeated field.
  virtual Iterator* PROTOBUF_NULLABLE
  BeginIterator(const Field* PROTOBUF_NONNULL data) const = 0;
  // Create an iterator that points at the end of the repeated field.
  virtual Iterator* PROTOBUF_NULLABLE
  EndIterator(const Field* PROTOBUF_NONNULL data) const = 0;
  // Make a copy of an iterator and return the new copy.
  virtual Iterator* PROTOBUF_NULLABLE
  CopyIterator(const Field* PROTOBUF_NONNULL data,
               const Iterator* PROTOBUF_NULLABLE iterator) const = 0;
  // Move an iterator to point to the next element.
  virtual Iterator* PROTOBUF_NONNULL
  AdvanceIterator(const Field* PROTOBUF_NONNULL data,
                  Iterator* PROTOBUF_NULLABLE iterator) const = 0;
  // Compare whether two iterators point to the same element.
  virtual bool EqualsIterator(const Field* PROTOBUF_NONNULL data,
                              const Iterator* PROTOBUF_NULLABLE a,
                              const Iterator* PROTOBUF_NULLABLE b) const = 0;
  // Delete an iterator created by BeginIterator(), EndIterator() and
  // CopyIterator().
  virtual void DeleteIterator(const Field* PROTOBUF_NONNULL data,
                              Iterator* PROTOBUF_NULLABLE iterator) const = 0;
  // Like Get() but for iterators.
  virtual const Value* PROTOBUF_NONNULL
  GetIteratorValue(const Field* PROTOBUF_NONNULL data,
                   const Iterator* PROTOBUF_NULLABLE iterator,
                   Value* PROTOBUF_NULLABLE scratch_space) const = 0;

  // Templated methods that make using this interface easier for non-message
  // types.
  template <typename T>
  T Get(const Field* PROTOBUF_NONNULL data, int index) const {
    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
    ActualType scratch_space;
    return static_cast<T>(*reinterpret_cast<const ActualType*>(
        Get(data, index, static_cast<Value*>(&scratch_space))));
  }

  template <typename T, typename ValueType>
  void Set(Field* PROTOBUF_NONNULL data, int index,
           const ValueType& value) const {
    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
    // In this RepeatedFieldAccessor interface we pass/return data using
    // raw pointers. Type of the data these raw pointers point to should
    // be ActualType. Here we have a ValueType object and want a ActualType
    // pointer. We can't cast a ValueType pointer to an ActualType pointer
    // directly because their type might be different (for enums ValueType
    // may be a generated enum type while ActualType is int32_t). To be safe
    // we make a copy to get a temporary ActualType object and use it.
    ActualType tmp = static_cast<ActualType>(value);
    Set(data, index, static_cast<const Value*>(&tmp));
  }

  template <typename T, typename ValueType>
  void Add(Field* PROTOBUF_NONNULL data, const ValueType& value) const {
    typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
    // In this RepeatedFieldAccessor interface we pass/return data using
    // raw pointers. Type of the data these raw pointers point to should
    // be ActualType. Here we have a ValueType object and want a ActualType
    // pointer. We can't cast a ValueType pointer to an ActualType pointer
    // directly because their type might be different (for enums ValueType
    // may be a generated enum type while ActualType is int32_t). To be safe
    // we make a copy to get a temporary ActualType object and use it.
    ActualType tmp = static_cast<ActualType>(value);
    Add(data, static_cast<const Value*>(&tmp));
  }

 protected:
  // We want the destructor to be completely trivial as to allow it to be
  // a function local static. Hence we make it non-virtual and protected,
  // this class only live as part of a global singleton and should not be
  // deleted.
  ~RepeatedFieldAccessor() = default;
};

// Implement (Mutable)RepeatedFieldRef::iterator
template <typename T>
class RepeatedFieldRefIterator {
  typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
  typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
  typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;

 public:
  using iterator_category = std::forward_iterator_tag;
  using value_type = T;
  using pointer = T*;
  using reference = T&;
  using difference_type = std::ptrdiff_t;

  // Constructor for non-message fields.
  RepeatedFieldRefIterator(
      const void* PROTOBUF_NONNULL data,
      const RepeatedFieldAccessor* PROTOBUF_NONNULL accessor, bool begin)
      : data_(data),
        accessor_(accessor),
        iterator_(begin ? accessor->BeginIterator(data)
                        : accessor->EndIterator(data)),
        // The end iterator must not be dereferenced, no need for scratch space.
        scratch_space_(begin ? new AccessorValueType : nullptr) {}
  // Constructor for message fields.
  RepeatedFieldRefIterator(
      const void* PROTOBUF_NONNULL data,
      const RepeatedFieldAccessor* PROTOBUF_NONNULL accessor, bool begin,
      AccessorValueType* PROTOBUF_NULLABLE scratch_space)
      : data_(data),
        accessor_(accessor),
        iterator_(begin ? accessor->BeginIterator(data)
                        : accessor->EndIterator(data)),
        scratch_space_(scratch_space) {}
  ~RepeatedFieldRefIterator() { accessor_->DeleteIterator(data_, iterator_); }
  RepeatedFieldRefIterator operator++(int) {
    RepeatedFieldRefIterator tmp(*this);
    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
    return tmp;
  }
  RepeatedFieldRefIterator& operator++() {
    iterator_ = accessor_->AdvanceIterator(data_, iterator_);
    return *this;
  }
  IteratorValueType operator*() const {
    return static_cast<IteratorValueType>(
        *static_cast<const AccessorValueType*>(accessor_->GetIteratorValue(
            data_, iterator_, scratch_space_.get())));
  }
  IteratorPointerType operator->() const {
    return static_cast<IteratorPointerType>(
        accessor_->GetIteratorValue(data_, iterator_, scratch_space_.get()));
  }
  bool operator!=(const RepeatedFieldRefIterator& other) const {
    assert(data_ == other.data_);
    assert(accessor_ == other.accessor_);
    return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
  }
  bool operator==(const RepeatedFieldRefIterator& other) const {
    return !this->operator!=(other);
  }

  RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
      : data_(other.data_),
        accessor_(other.accessor_),
        iterator_(accessor_->CopyIterator(data_, other.iterator_)) {}
  RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
    if (this != &other) {
      accessor_->DeleteIterator(data_, iterator_);
      data_ = other.data_;
      accessor_ = other.accessor_;
      iterator_ = accessor_->CopyIterator(data_, other.iterator_);
    }
    return *this;
  }

 protected:
  const void* PROTOBUF_NONNULL data_;
  const RepeatedFieldAccessor* PROTOBUF_NONNULL accessor_;
  void* PROTOBUF_NULLABLE iterator_;
  std::unique_ptr<AccessorValueType> scratch_space_;
};

// TypeTraits that maps the type parameter T of RepeatedFieldRef or
// MutableRepeatedFieldRef to corresponding iterator type,
// RepeatedFieldAccessor type, etc.
template <typename T>
struct PrimitiveTraits {
  static constexpr bool is_primitive = false;
};
#define DEFINE_PRIMITIVE(TYPE, type)                 \
  template <>                                        \
  struct PrimitiveTraits<type> {                     \
    static const bool is_primitive = true;           \
    static const FieldDescriptor::CppType cpp_type = \
        FieldDescriptor::CPPTYPE_##TYPE;             \
  };
DEFINE_PRIMITIVE(INT32, int32_t)
DEFINE_PRIMITIVE(UINT32, uint32_t)
DEFINE_PRIMITIVE(INT64, int64_t)
DEFINE_PRIMITIVE(UINT64, uint64_t)
DEFINE_PRIMITIVE(FLOAT, float)
DEFINE_PRIMITIVE(DOUBLE, double)
DEFINE_PRIMITIVE(BOOL, bool)
#undef DEFINE_PRIMITIVE

template <typename T>
struct RefTypeTraits<
    T, typename std::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  typedef T AccessorValueType;
  typedef T IteratorValueType;
  typedef T* IteratorPointerType;
  static constexpr FieldDescriptor::CppType cpp_type =
      PrimitiveTraits<T>::cpp_type;
  static const Descriptor* PROTOBUF_NULLABLE GetMessageFieldDescriptor() {
    return nullptr;
  }
};

template <typename T>
struct RefTypeTraits<
    T, typename std::enable_if<is_proto_enum<T>::value>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  // We use int32_t for repeated enums in RepeatedFieldAccessor.
  typedef int32_t AccessorValueType;
  typedef T IteratorValueType;
  typedef int32_t* IteratorPointerType;
  static constexpr FieldDescriptor::CppType cpp_type =
      FieldDescriptor::CPPTYPE_ENUM;
  static const Descriptor* PROTOBUF_NULLABLE GetMessageFieldDescriptor() {
    return nullptr;
  }
};

template <typename T>
struct RefTypeTraits<
    T, typename std::enable_if<std::is_same<std::string, T>::value>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  typedef std::string AccessorValueType;
  typedef const std::string IteratorValueType;
  typedef const std::string* IteratorPointerType;
  static constexpr FieldDescriptor::CppType cpp_type =
      FieldDescriptor::CPPTYPE_STRING;
  static const Descriptor* PROTOBUF_NULLABLE GetMessageFieldDescriptor() {
    return nullptr;
  }
};

template <typename T>
struct MessageDescriptorGetter {
  static const Descriptor* PROTOBUF_NONNULL get() {
    return T::default_instance().GetDescriptor();
  }
};
template <>
struct MessageDescriptorGetter<Message> {
  static const Descriptor* PROTOBUF_NULLABLE get() { return nullptr; }
};

template <typename T>
struct RefTypeTraits<
    T, typename std::enable_if<std::is_base_of<Message, T>::value>::type> {
  typedef RepeatedFieldRefIterator<T> iterator;
  typedef RepeatedFieldAccessor AccessorType;
  typedef Message AccessorValueType;
  typedef const T& IteratorValueType;
  typedef const T* IteratorPointerType;
  static constexpr FieldDescriptor::CppType cpp_type =
      FieldDescriptor::CPPTYPE_MESSAGE;
  static const Descriptor* PROTOBUF_NULLABLE GetMessageFieldDescriptor() {
    return MessageDescriptorGetter<T>::get();
  }
};
}  // namespace internal
}  // namespace protobuf
}  // namespace google

#include "google/protobuf/port_undef.inc"

#endif  // GOOGLE_PROTOBUF_REFLECTION_H__
