// 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.

#ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
#define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__

#include <string>

#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/message_lite.h"
#include "google/protobuf/repeated_field.h"

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

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

// This file is logically internal-only and should only be used by protobuf
// generated code.

namespace google {
namespace protobuf {
namespace internal {

// An implementation of MessageLite that treats all data as unknown. This type
// acts as a placeholder for an implicit weak field in the case where the true
// message type does not get linked into the binary.
class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite {
 public:
  ImplicitWeakMessage() : data_(new std::string) {}
  explicit constexpr ImplicitWeakMessage(ConstantInitialized)
      : data_(nullptr) {}
  explicit ImplicitWeakMessage(Arena* arena)
      : MessageLite(arena), data_(new std::string) {}
  ImplicitWeakMessage(const ImplicitWeakMessage&) = delete;
  ImplicitWeakMessage& operator=(const ImplicitWeakMessage&) = delete;

  ~ImplicitWeakMessage() override {
    // data_ will be null in the default instance, but we can safely call delete
    // here because the default instance will never be destroyed.
    delete data_;
  }

  static const ImplicitWeakMessage* default_instance();

  std::string GetTypeName() const override { return ""; }

  MessageLite* New(Arena* arena) const override {
    return Arena::CreateMessage<ImplicitWeakMessage>(arena);
  }

  void Clear() override { data_->clear(); }

  bool IsInitialized() const override { return true; }

  void CheckTypeAndMergeFrom(const MessageLite& other) override {
    const std::string* other_data =
        static_cast<const ImplicitWeakMessage&>(other).data_;
    if (other_data != nullptr) {
      data_->append(*other_data);
    }
  }

  const char* _InternalParse(const char* ptr, ParseContext* ctx) final;

  size_t ByteSizeLong() const override {
    return data_ == nullptr ? 0 : data_->size();
  }

  uint8_t* _InternalSerialize(uint8_t* target,
                              io::EpsCopyOutputStream* stream) const final {
    if (data_ == nullptr) {
      return target;
    }
    return stream->WriteRaw(data_->data(), static_cast<int>(data_->size()),
                            target);
  }

  int GetCachedSize() const override {
    return data_ == nullptr ? 0 : static_cast<int>(data_->size());
  }

  typedef void InternalArenaConstructable_;

 private:
  // This std::string is allocated on the heap, but we use a raw pointer so that
  // the default instance can be constant-initialized. In the const methods, we
  // have to handle the possibility of data_ being null.
  std::string* data_;
};

struct ImplicitWeakMessageDefaultType;
extern ImplicitWeakMessageDefaultType implicit_weak_message_default_instance;

// A type handler for use with implicit weak repeated message fields.
template <typename ImplicitWeakType>
class ImplicitWeakTypeHandler {
 public:
  typedef MessageLite Type;
  static constexpr bool Moveable = false;

  static inline MessageLite* NewFromPrototype(const MessageLite* prototype,
                                              Arena* arena = nullptr) {
    return prototype->New(arena);
  }

  static inline void Delete(MessageLite* value, Arena* arena) {
    if (arena == nullptr) {
      delete value;
    }
  }
  static inline Arena* GetArena(MessageLite* value) {
    return value->GetArena();
  }
  static inline void Clear(MessageLite* value) { value->Clear(); }
  static void Merge(const MessageLite& from, MessageLite* to) {
    to->CheckTypeAndMergeFrom(from);
  }
};

}  // namespace internal

template <typename T>
struct WeakRepeatedPtrField {
  using TypeHandler = internal::ImplicitWeakTypeHandler<T>;
  constexpr WeakRepeatedPtrField() : weak() {}
  explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {}
  ~WeakRepeatedPtrField() { weak.template Destroy<TypeHandler>(); }

  typedef internal::RepeatedPtrIterator<MessageLite> iterator;
  typedef internal::RepeatedPtrIterator<const MessageLite> const_iterator;
  typedef internal::RepeatedPtrOverPtrsIterator<MessageLite*, void*>
      pointer_iterator;
  typedef internal::RepeatedPtrOverPtrsIterator<const MessageLite* const,
                                                const void* const>
      const_pointer_iterator;

  iterator begin() { return iterator(base().raw_data()); }
  const_iterator begin() const { return iterator(base().raw_data()); }
  const_iterator cbegin() const { return begin(); }
  iterator end() { return begin() + base().size(); }
  const_iterator end() const { return begin() + base().size(); }
  const_iterator cend() const { return end(); }
  pointer_iterator pointer_begin() {
    return pointer_iterator(base().raw_mutable_data());
  }
  const_pointer_iterator pointer_begin() const {
    return const_pointer_iterator(base().raw_mutable_data());
  }
  pointer_iterator pointer_end() {
    return pointer_iterator(base().raw_mutable_data() + base().size());
  }
  const_pointer_iterator pointer_end() const {
    return const_pointer_iterator(base().raw_mutable_data() + base().size());
  }

  MessageLite* AddWeak(const MessageLite* prototype) {
    return base().AddWeak(prototype);
  }
  T* Add() { return weak.Add(); }
  void Clear() { base().template Clear<TypeHandler>(); }
  void MergeFrom(const WeakRepeatedPtrField& other) {
    base().template MergeFrom<TypeHandler>(other.base());
  }
  void InternalSwap(WeakRepeatedPtrField* other) {
    base().InternalSwap(&other->base());
  }

  const internal::RepeatedPtrFieldBase& base() const { return weak; }
  internal::RepeatedPtrFieldBase& base() { return weak; }
  // Union disables running the destructor. Which would create a strong link.
  // Instead we explicitly destroy the underlying base through the virtual
  // destructor.
  union {
    RepeatedPtrField<T> weak;
  };
};

}  // namespace protobuf
}  // namespace google

#include "google/protobuf/port_undef.inc"

#endif  // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
