// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// 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 <google/protobuf/message.h>
#include <google/protobuf/generated_enum_util.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

template <typename T>
RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
    const Message& message, const FieldDescriptor* field) const {
  return RepeatedFieldRef<T>(message, field);
}

template <typename T>
MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
    Message* message, const FieldDescriptor* field) const {
  return MutableRepeatedFieldRef<T>(message, field);
}

// 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 Message& message, const FieldDescriptor* field) {
    const Reflection* reflection = message.GetReflection();
    data_ = reflection->RepeatedFieldData(const_cast<Message*>(&message), field,
                                          internal::RefTypeTraits<T>::cpp_type,
                                          nullptr);
    accessor_ = reflection->RepeatedFieldAccessor(field);
  }

  const void* data_;
  const AccessorType* 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(Message* message, const FieldDescriptor* field) {
    const Reflection* reflection = message->GetReflection();
    data_ = reflection->RepeatedFieldData(
        message, field, internal::RefTypeTraits<T>::cpp_type, nullptr);
    accessor_ = reflection->RepeatedFieldAccessor(field);
  }

  void* data_;
  const AccessorType* 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* 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* NewMessage() const { return static_cast<T*>(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 Message& message, const FieldDescriptor* field) {
    const Reflection* reflection = message.GetReflection();
    data_ = reflection->RepeatedFieldData(
        const_cast<Message*>(&message), field,
        internal::RefTypeTraits<T>::cpp_type,
        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
    accessor_ = reflection->RepeatedFieldAccessor(field);
    default_instance_ =
        reflection->GetMessageFactory()->GetPrototype(field->message_type());
  }

  const void* data_;
  const AccessorType* accessor_;
  const Message* 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* 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* NewMessage() const { return static_cast<T*>(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(Message* message, const FieldDescriptor* field) {
    const Reflection* reflection = message->GetReflection();
    data_ = reflection->RepeatedFieldData(
        message, field, internal::RefTypeTraits<T>::cpp_type,
        internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
    accessor_ = reflection->RepeatedFieldAccessor(field);
    default_instance_ =
        reflection->GetMessageFactory()->GetPrototype(field->message_type());
  }

  void* data_;
  const AccessorType* accessor_;
  const Message* 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* data) const = 0;
  virtual int Size(const Field* 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* Get(const Field* data, int index,
                           Value* scratch_space) const = 0;

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

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

  // Templated methods that make using this interface easier for non-message
  // types.
  template <typename T>
  T Get(const Field* 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* 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* 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* data,
                           const RepeatedFieldAccessor* 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* data,
                           const RepeatedFieldAccessor* accessor, bool begin,
                           AccessorValueType* 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* data_;
  const RepeatedFieldAccessor* accessor_;
  void* 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* 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* 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* GetMessageFieldDescriptor() { return nullptr; }
};

template <typename T>
struct MessageDescriptorGetter {
  static const Descriptor* get() {
    return T::default_instance().GetDescriptor();
  }
};
template <>
struct MessageDescriptorGetter<Message> {
  static const Descriptor* 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* GetMessageFieldDescriptor() {
    return MessageDescriptorGetter<T>::get();
  }
};
}  // namespace internal
}  // namespace protobuf
}  // namespace google

#include <google/protobuf/port_undef.inc>

#endif  // GOOGLE_PROTOBUF_REFLECTION_H__
