// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/protobuf/api.proto

#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto

#include <limits>
#include <string>

#include <google/protobuf/port_def.inc>
#if PROTOBUF_VERSION < 3021000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3021009 < PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif

#include <google/protobuf/port_undef.inc>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/metadata_lite.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
#include <google/protobuf/extension_set.h>  // IWYU pragma: export
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/source_context.pb.h>
#include <google/protobuf/type.pb.h>
// @@protoc_insertion_point(includes)
#include <google/protobuf/port_def.inc>
#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto PROTOBUF_EXPORT
PROTOBUF_NAMESPACE_OPEN
namespace internal {
class AnyMetadata;
}  // namespace internal
PROTOBUF_NAMESPACE_CLOSE

// Internal implementation detail -- do not use these members.
struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto {
  static const uint32_t offsets[];
};
PROTOBUF_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto;
PROTOBUF_NAMESPACE_OPEN
class Api;
struct ApiDefaultTypeInternal;
PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_;
class Method;
struct MethodDefaultTypeInternal;
PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_;
class Mixin;
struct MixinDefaultTypeInternal;
PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
PROTOBUF_NAMESPACE_CLOSE
PROTOBUF_NAMESPACE_OPEN
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Api* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Api>(Arena*);
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Method* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Method>(Arena*);
template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Mixin* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Mixin>(Arena*);
PROTOBUF_NAMESPACE_CLOSE
PROTOBUF_NAMESPACE_OPEN

// ===================================================================

class PROTOBUF_EXPORT Api final :
    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ {
 public:
  inline Api() : Api(nullptr) {}
  ~Api() override;
  explicit PROTOBUF_CONSTEXPR Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);

  Api(const Api& from);
  Api(Api&& from) noexcept
    : Api() {
    *this = ::std::move(from);
  }

  inline Api& operator=(const Api& from) {
    CopyFrom(from);
    return *this;
  }
  inline Api& operator=(Api&& from) noexcept {
    if (this == &from) return *this;
    if (GetOwningArena() == from.GetOwningArena()
  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
        && GetOwningArena() != nullptr
  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
    ) {
      InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }

  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
    return GetDescriptor();
  }
  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
    return default_instance().GetMetadata().descriptor;
  }
  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
    return default_instance().GetMetadata().reflection;
  }
  static const Api& default_instance() {
    return *internal_default_instance();
  }
  static inline const Api* internal_default_instance() {
    return reinterpret_cast<const Api*>(
               &_Api_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    0;

  friend void swap(Api& a, Api& b) {
    a.Swap(&b);
  }
  inline void Swap(Api* other) {
    if (other == this) return;
  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
    if (GetOwningArena() != nullptr &&
        GetOwningArena() == other->GetOwningArena()) {
   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
    if (GetOwningArena() == other->GetOwningArena()) {
  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
      InternalSwap(other);
    } else {
      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
    }
  }
  void UnsafeArenaSwap(Api* other) {
    if (other == this) return;
    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
    InternalSwap(other);
  }

  // implements Message ----------------------------------------------

  Api* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
    return CreateMaybeMessage<Api>(arena);
  }
  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
  void CopyFrom(const Api& from);
  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
  void MergeFrom( const Api& from) {
    Api::MergeImpl(*this, from);
  }
  private:
  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
  public:
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
  uint8_t* _InternalSerialize(
      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }

  private:
  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(Api* other);

  private:
  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
    return "google.protobuf.Api";
  }
  protected:
  explicit Api(::PROTOBUF_NAMESPACE_ID::Arena* arena,
                       bool is_message_owned = false);
  public:

  static const ClassData _class_data_;
  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;

  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  enum : int {
    kMethodsFieldNumber = 2,
    kOptionsFieldNumber = 3,
    kMixinsFieldNumber = 6,
    kNameFieldNumber = 1,
    kVersionFieldNumber = 4,
    kSourceContextFieldNumber = 5,
    kSyntaxFieldNumber = 7,
  };
  // repeated .google.protobuf.Method methods = 2;
  int methods_size() const;
  private:
  int _internal_methods_size() const;
  public:
  void clear_methods();
  ::PROTOBUF_NAMESPACE_ID::Method* mutable_methods(int index);
  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >*
      mutable_methods();
  private:
  const ::PROTOBUF_NAMESPACE_ID::Method& _internal_methods(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Method* _internal_add_methods();
  public:
  const ::PROTOBUF_NAMESPACE_ID::Method& methods(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Method* add_methods();
  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >&
      methods() const;

  // repeated .google.protobuf.Option options = 3;
  int options_size() const;
  private:
  int _internal_options_size() const;
  public:
  void clear_options();
  ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index);
  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >*
      mutable_options();
  private:
  const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options();
  public:
  const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Option* add_options();
  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >&
      options() const;

  // repeated .google.protobuf.Mixin mixins = 6;
  int mixins_size() const;
  private:
  int _internal_mixins_size() const;
  public:
  void clear_mixins();
  ::PROTOBUF_NAMESPACE_ID::Mixin* mutable_mixins(int index);
  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >*
      mutable_mixins();
  private:
  const ::PROTOBUF_NAMESPACE_ID::Mixin& _internal_mixins(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Mixin* _internal_add_mixins();
  public:
  const ::PROTOBUF_NAMESPACE_ID::Mixin& mixins(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Mixin* add_mixins();
  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >&
      mixins() const;

  // string name = 1;
  void clear_name();
  const std::string& name() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_name(ArgT0&& arg0, ArgT... args);
  std::string* mutable_name();
  PROTOBUF_NODISCARD std::string* release_name();
  void set_allocated_name(std::string* name);
  private:
  const std::string& _internal_name() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
  std::string* _internal_mutable_name();
  public:

  // string version = 4;
  void clear_version();
  const std::string& version() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_version(ArgT0&& arg0, ArgT... args);
  std::string* mutable_version();
  PROTOBUF_NODISCARD std::string* release_version();
  void set_allocated_version(std::string* version);
  private:
  const std::string& _internal_version() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_version(const std::string& value);
  std::string* _internal_mutable_version();
  public:

  // .google.protobuf.SourceContext source_context = 5;
  bool has_source_context() const;
  private:
  bool _internal_has_source_context() const;
  public:
  void clear_source_context();
  const ::PROTOBUF_NAMESPACE_ID::SourceContext& source_context() const;
  PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceContext* release_source_context();
  ::PROTOBUF_NAMESPACE_ID::SourceContext* mutable_source_context();
  void set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
  private:
  const ::PROTOBUF_NAMESPACE_ID::SourceContext& _internal_source_context() const;
  ::PROTOBUF_NAMESPACE_ID::SourceContext* _internal_mutable_source_context();
  public:
  void unsafe_arena_set_allocated_source_context(
      ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context);
  ::PROTOBUF_NAMESPACE_ID::SourceContext* unsafe_arena_release_source_context();

  // .google.protobuf.Syntax syntax = 7;
  void clear_syntax();
  ::PROTOBUF_NAMESPACE_ID::Syntax syntax() const;
  void set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value);
  private:
  ::PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const;
  void _internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value);
  public:

  // @@protoc_insertion_point(class_scope:google.protobuf.Api)
 private:
  class _Internal;

  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
  typedef void InternalArenaConstructable_;
  typedef void DestructorSkippable_;
  struct Impl_ {
    ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method > methods_;
    ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_;
    ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin > mixins_;
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr version_;
    ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context_;
    int syntax_;
    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
  };
  union { Impl_ _impl_; };
  friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto;
};
// -------------------------------------------------------------------

class PROTOBUF_EXPORT Method final :
    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ {
 public:
  inline Method() : Method(nullptr) {}
  ~Method() override;
  explicit PROTOBUF_CONSTEXPR Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);

  Method(const Method& from);
  Method(Method&& from) noexcept
    : Method() {
    *this = ::std::move(from);
  }

  inline Method& operator=(const Method& from) {
    CopyFrom(from);
    return *this;
  }
  inline Method& operator=(Method&& from) noexcept {
    if (this == &from) return *this;
    if (GetOwningArena() == from.GetOwningArena()
  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
        && GetOwningArena() != nullptr
  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
    ) {
      InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }

  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
    return GetDescriptor();
  }
  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
    return default_instance().GetMetadata().descriptor;
  }
  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
    return default_instance().GetMetadata().reflection;
  }
  static const Method& default_instance() {
    return *internal_default_instance();
  }
  static inline const Method* internal_default_instance() {
    return reinterpret_cast<const Method*>(
               &_Method_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    1;

  friend void swap(Method& a, Method& b) {
    a.Swap(&b);
  }
  inline void Swap(Method* other) {
    if (other == this) return;
  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
    if (GetOwningArena() != nullptr &&
        GetOwningArena() == other->GetOwningArena()) {
   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
    if (GetOwningArena() == other->GetOwningArena()) {
  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
      InternalSwap(other);
    } else {
      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
    }
  }
  void UnsafeArenaSwap(Method* other) {
    if (other == this) return;
    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
    InternalSwap(other);
  }

  // implements Message ----------------------------------------------

  Method* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
    return CreateMaybeMessage<Method>(arena);
  }
  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
  void CopyFrom(const Method& from);
  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
  void MergeFrom( const Method& from) {
    Method::MergeImpl(*this, from);
  }
  private:
  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
  public:
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
  uint8_t* _InternalSerialize(
      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }

  private:
  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(Method* other);

  private:
  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
    return "google.protobuf.Method";
  }
  protected:
  explicit Method(::PROTOBUF_NAMESPACE_ID::Arena* arena,
                       bool is_message_owned = false);
  public:

  static const ClassData _class_data_;
  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;

  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  enum : int {
    kOptionsFieldNumber = 6,
    kNameFieldNumber = 1,
    kRequestTypeUrlFieldNumber = 2,
    kResponseTypeUrlFieldNumber = 4,
    kRequestStreamingFieldNumber = 3,
    kResponseStreamingFieldNumber = 5,
    kSyntaxFieldNumber = 7,
  };
  // repeated .google.protobuf.Option options = 6;
  int options_size() const;
  private:
  int _internal_options_size() const;
  public:
  void clear_options();
  ::PROTOBUF_NAMESPACE_ID::Option* mutable_options(int index);
  ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >*
      mutable_options();
  private:
  const ::PROTOBUF_NAMESPACE_ID::Option& _internal_options(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Option* _internal_add_options();
  public:
  const ::PROTOBUF_NAMESPACE_ID::Option& options(int index) const;
  ::PROTOBUF_NAMESPACE_ID::Option* add_options();
  const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >&
      options() const;

  // string name = 1;
  void clear_name();
  const std::string& name() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_name(ArgT0&& arg0, ArgT... args);
  std::string* mutable_name();
  PROTOBUF_NODISCARD std::string* release_name();
  void set_allocated_name(std::string* name);
  private:
  const std::string& _internal_name() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
  std::string* _internal_mutable_name();
  public:

  // string request_type_url = 2;
  void clear_request_type_url();
  const std::string& request_type_url() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_request_type_url(ArgT0&& arg0, ArgT... args);
  std::string* mutable_request_type_url();
  PROTOBUF_NODISCARD std::string* release_request_type_url();
  void set_allocated_request_type_url(std::string* request_type_url);
  private:
  const std::string& _internal_request_type_url() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_request_type_url(const std::string& value);
  std::string* _internal_mutable_request_type_url();
  public:

  // string response_type_url = 4;
  void clear_response_type_url();
  const std::string& response_type_url() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_response_type_url(ArgT0&& arg0, ArgT... args);
  std::string* mutable_response_type_url();
  PROTOBUF_NODISCARD std::string* release_response_type_url();
  void set_allocated_response_type_url(std::string* response_type_url);
  private:
  const std::string& _internal_response_type_url() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_response_type_url(const std::string& value);
  std::string* _internal_mutable_response_type_url();
  public:

  // bool request_streaming = 3;
  void clear_request_streaming();
  bool request_streaming() const;
  void set_request_streaming(bool value);
  private:
  bool _internal_request_streaming() const;
  void _internal_set_request_streaming(bool value);
  public:

  // bool response_streaming = 5;
  void clear_response_streaming();
  bool response_streaming() const;
  void set_response_streaming(bool value);
  private:
  bool _internal_response_streaming() const;
  void _internal_set_response_streaming(bool value);
  public:

  // .google.protobuf.Syntax syntax = 7;
  void clear_syntax();
  ::PROTOBUF_NAMESPACE_ID::Syntax syntax() const;
  void set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value);
  private:
  ::PROTOBUF_NAMESPACE_ID::Syntax _internal_syntax() const;
  void _internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value);
  public:

  // @@protoc_insertion_point(class_scope:google.protobuf.Method)
 private:
  class _Internal;

  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
  typedef void InternalArenaConstructable_;
  typedef void DestructorSkippable_;
  struct Impl_ {
    ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_;
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr request_type_url_;
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr response_type_url_;
    bool request_streaming_;
    bool response_streaming_;
    int syntax_;
    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
  };
  union { Impl_ _impl_; };
  friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto;
};
// -------------------------------------------------------------------

class PROTOBUF_EXPORT Mixin final :
    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ {
 public:
  inline Mixin() : Mixin(nullptr) {}
  ~Mixin() override;
  explicit PROTOBUF_CONSTEXPR Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);

  Mixin(const Mixin& from);
  Mixin(Mixin&& from) noexcept
    : Mixin() {
    *this = ::std::move(from);
  }

  inline Mixin& operator=(const Mixin& from) {
    CopyFrom(from);
    return *this;
  }
  inline Mixin& operator=(Mixin&& from) noexcept {
    if (this == &from) return *this;
    if (GetOwningArena() == from.GetOwningArena()
  #ifdef PROTOBUF_FORCE_COPY_IN_MOVE
        && GetOwningArena() != nullptr
  #endif  // !PROTOBUF_FORCE_COPY_IN_MOVE
    ) {
      InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }

  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
    return GetDescriptor();
  }
  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
    return default_instance().GetMetadata().descriptor;
  }
  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
    return default_instance().GetMetadata().reflection;
  }
  static const Mixin& default_instance() {
    return *internal_default_instance();
  }
  static inline const Mixin* internal_default_instance() {
    return reinterpret_cast<const Mixin*>(
               &_Mixin_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    2;

  friend void swap(Mixin& a, Mixin& b) {
    a.Swap(&b);
  }
  inline void Swap(Mixin* other) {
    if (other == this) return;
  #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
    if (GetOwningArena() != nullptr &&
        GetOwningArena() == other->GetOwningArena()) {
   #else  // PROTOBUF_FORCE_COPY_IN_SWAP
    if (GetOwningArena() == other->GetOwningArena()) {
  #endif  // !PROTOBUF_FORCE_COPY_IN_SWAP
      InternalSwap(other);
    } else {
      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
    }
  }
  void UnsafeArenaSwap(Mixin* other) {
    if (other == this) return;
    GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena());
    InternalSwap(other);
  }

  // implements Message ----------------------------------------------

  Mixin* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final {
    return CreateMaybeMessage<Mixin>(arena);
  }
  using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
  void CopyFrom(const Mixin& from);
  using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
  void MergeFrom( const Mixin& from) {
    Mixin::MergeImpl(*this, from);
  }
  private:
  static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg);
  public:
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
  uint8_t* _InternalSerialize(
      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
  int GetCachedSize() const final { return _impl_._cached_size_.Get(); }

  private:
  void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned);
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(Mixin* other);

  private:
  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
    return "google.protobuf.Mixin";
  }
  protected:
  explicit Mixin(::PROTOBUF_NAMESPACE_ID::Arena* arena,
                       bool is_message_owned = false);
  public:

  static const ClassData _class_data_;
  const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final;

  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  enum : int {
    kNameFieldNumber = 1,
    kRootFieldNumber = 2,
  };
  // string name = 1;
  void clear_name();
  const std::string& name() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_name(ArgT0&& arg0, ArgT... args);
  std::string* mutable_name();
  PROTOBUF_NODISCARD std::string* release_name();
  void set_allocated_name(std::string* name);
  private:
  const std::string& _internal_name() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value);
  std::string* _internal_mutable_name();
  public:

  // string root = 2;
  void clear_root();
  const std::string& root() const;
  template <typename ArgT0 = const std::string&, typename... ArgT>
  void set_root(ArgT0&& arg0, ArgT... args);
  std::string* mutable_root();
  PROTOBUF_NODISCARD std::string* release_root();
  void set_allocated_root(std::string* root);
  private:
  const std::string& _internal_root() const;
  inline PROTOBUF_ALWAYS_INLINE void _internal_set_root(const std::string& value);
  std::string* _internal_mutable_root();
  public:

  // @@protoc_insertion_point(class_scope:google.protobuf.Mixin)
 private:
  class _Internal;

  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
  typedef void InternalArenaConstructable_;
  typedef void DestructorSkippable_;
  struct Impl_ {
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr root_;
    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
  };
  union { Impl_ _impl_; };
  friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto;
};
// ===================================================================


// ===================================================================

#ifdef __GNUC__
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif  // __GNUC__
// Api

// string name = 1;
inline void Api::clear_name() {
  _impl_.name_.ClearToEmpty();
}
inline const std::string& Api::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
  return _internal_name();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Api::set_name(ArgT0&& arg0, ArgT... args) {
 
 _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
}
inline std::string* Api::mutable_name() {
  std::string* _s = _internal_mutable_name();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.name)
  return _s;
}
inline const std::string& Api::_internal_name() const {
  return _impl_.name_.Get();
}
inline void Api::_internal_set_name(const std::string& value) {
  
  _impl_.name_.Set(value, GetArenaForAllocation());
}
inline std::string* Api::_internal_mutable_name() {
  
  return _impl_.name_.Mutable(GetArenaForAllocation());
}
inline std::string* Api::release_name() {
  // @@protoc_insertion_point(field_release:google.protobuf.Api.name)
  return _impl_.name_.Release();
}
inline void Api::set_allocated_name(std::string* name) {
  if (name != nullptr) {
    
  } else {
    
  }
  _impl_.name_.SetAllocated(name, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.name_.IsDefault()) {
    _impl_.name_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name)
}

// repeated .google.protobuf.Method methods = 2;
inline int Api::_internal_methods_size() const {
  return _impl_.methods_.size();
}
inline int Api::methods_size() const {
  return _internal_methods_size();
}
inline void Api::clear_methods() {
  _impl_.methods_.Clear();
}
inline ::PROTOBUF_NAMESPACE_ID::Method* Api::mutable_methods(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
  return _impl_.methods_.Mutable(index);
}
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >*
Api::mutable_methods() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
  return &_impl_.methods_;
}
inline const ::PROTOBUF_NAMESPACE_ID::Method& Api::_internal_methods(int index) const {
  return _impl_.methods_.Get(index);
}
inline const ::PROTOBUF_NAMESPACE_ID::Method& Api::methods(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
  return _internal_methods(index);
}
inline ::PROTOBUF_NAMESPACE_ID::Method* Api::_internal_add_methods() {
  return _impl_.methods_.Add();
}
inline ::PROTOBUF_NAMESPACE_ID::Method* Api::add_methods() {
  ::PROTOBUF_NAMESPACE_ID::Method* _add = _internal_add_methods();
  // @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
  return _add;
}
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Method >&
Api::methods() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
  return _impl_.methods_;
}

// repeated .google.protobuf.Option options = 3;
inline int Api::_internal_options_size() const {
  return _impl_.options_.size();
}
inline int Api::options_size() const {
  return _internal_options_size();
}
inline ::PROTOBUF_NAMESPACE_ID::Option* Api::mutable_options(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
  return _impl_.options_.Mutable(index);
}
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >*
Api::mutable_options() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
  return &_impl_.options_;
}
inline const ::PROTOBUF_NAMESPACE_ID::Option& Api::_internal_options(int index) const {
  return _impl_.options_.Get(index);
}
inline const ::PROTOBUF_NAMESPACE_ID::Option& Api::options(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.options)
  return _internal_options(index);
}
inline ::PROTOBUF_NAMESPACE_ID::Option* Api::_internal_add_options() {
  return _impl_.options_.Add();
}
inline ::PROTOBUF_NAMESPACE_ID::Option* Api::add_options() {
  ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
  // @@protoc_insertion_point(field_add:google.protobuf.Api.options)
  return _add;
}
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >&
Api::options() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Api.options)
  return _impl_.options_;
}

// string version = 4;
inline void Api::clear_version() {
  _impl_.version_.ClearToEmpty();
}
inline const std::string& Api::version() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
  return _internal_version();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Api::set_version(ArgT0&& arg0, ArgT... args) {
 
 _impl_.version_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
}
inline std::string* Api::mutable_version() {
  std::string* _s = _internal_mutable_version();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.version)
  return _s;
}
inline const std::string& Api::_internal_version() const {
  return _impl_.version_.Get();
}
inline void Api::_internal_set_version(const std::string& value) {
  
  _impl_.version_.Set(value, GetArenaForAllocation());
}
inline std::string* Api::_internal_mutable_version() {
  
  return _impl_.version_.Mutable(GetArenaForAllocation());
}
inline std::string* Api::release_version() {
  // @@protoc_insertion_point(field_release:google.protobuf.Api.version)
  return _impl_.version_.Release();
}
inline void Api::set_allocated_version(std::string* version) {
  if (version != nullptr) {
    
  } else {
    
  }
  _impl_.version_.SetAllocated(version, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.version_.IsDefault()) {
    _impl_.version_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
}

// .google.protobuf.SourceContext source_context = 5;
inline bool Api::_internal_has_source_context() const {
  return this != internal_default_instance() && _impl_.source_context_ != nullptr;
}
inline bool Api::has_source_context() const {
  return _internal_has_source_context();
}
inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Api::_internal_source_context() const {
  const ::PROTOBUF_NAMESPACE_ID::SourceContext* p = _impl_.source_context_;
  return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::SourceContext&>(
      ::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_);
}
inline const ::PROTOBUF_NAMESPACE_ID::SourceContext& Api::source_context() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
  return _internal_source_context();
}
inline void Api::unsafe_arena_set_allocated_source_context(
    ::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
  if (GetArenaForAllocation() == nullptr) {
    delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_);
  }
  _impl_.source_context_ = source_context;
  if (source_context) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context)
}
inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() {
  
  ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_;
  _impl_.source_context_ = nullptr;
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
  auto* old =  reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp);
  temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
  if (GetArenaForAllocation() == nullptr) { delete old; }
#else  // PROTOBUF_FORCE_COPY_IN_RELEASE
  if (GetArenaForAllocation() != nullptr) {
    temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
  }
#endif  // !PROTOBUF_FORCE_COPY_IN_RELEASE
  return temp;
}
inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::unsafe_arena_release_source_context() {
  // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context)
  
  ::PROTOBUF_NAMESPACE_ID::SourceContext* temp = _impl_.source_context_;
  _impl_.source_context_ = nullptr;
  return temp;
}
inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::_internal_mutable_source_context() {
  
  if (_impl_.source_context_ == nullptr) {
    auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(GetArenaForAllocation());
    _impl_.source_context_ = p;
  }
  return _impl_.source_context_;
}
inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::mutable_source_context() {
  ::PROTOBUF_NAMESPACE_ID::SourceContext* _msg = _internal_mutable_source_context();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
  return _msg;
}
inline void Api::set_allocated_source_context(::PROTOBUF_NAMESPACE_ID::SourceContext* source_context) {
  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation();
  if (message_arena == nullptr) {
    delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_);
  }
  if (source_context) {
    ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
        ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(
                reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(source_context));
    if (message_arena != submessage_arena) {
      source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
          message_arena, source_context, submessage_arena);
    }
    
  } else {
    
  }
  _impl_.source_context_ = source_context;
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
}

// repeated .google.protobuf.Mixin mixins = 6;
inline int Api::_internal_mixins_size() const {
  return _impl_.mixins_.size();
}
inline int Api::mixins_size() const {
  return _internal_mixins_size();
}
inline void Api::clear_mixins() {
  _impl_.mixins_.Clear();
}
inline ::PROTOBUF_NAMESPACE_ID::Mixin* Api::mutable_mixins(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins)
  return _impl_.mixins_.Mutable(index);
}
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >*
Api::mutable_mixins() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
  return &_impl_.mixins_;
}
inline const ::PROTOBUF_NAMESPACE_ID::Mixin& Api::_internal_mixins(int index) const {
  return _impl_.mixins_.Get(index);
}
inline const ::PROTOBUF_NAMESPACE_ID::Mixin& Api::mixins(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
  return _internal_mixins(index);
}
inline ::PROTOBUF_NAMESPACE_ID::Mixin* Api::_internal_add_mixins() {
  return _impl_.mixins_.Add();
}
inline ::PROTOBUF_NAMESPACE_ID::Mixin* Api::add_mixins() {
  ::PROTOBUF_NAMESPACE_ID::Mixin* _add = _internal_add_mixins();
  // @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
  return _add;
}
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Mixin >&
Api::mixins() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Api.mixins)
  return _impl_.mixins_;
}

// .google.protobuf.Syntax syntax = 7;
inline void Api::clear_syntax() {
  _impl_.syntax_ = 0;
}
inline ::PROTOBUF_NAMESPACE_ID::Syntax Api::_internal_syntax() const {
  return static_cast< ::PROTOBUF_NAMESPACE_ID::Syntax >(_impl_.syntax_);
}
inline ::PROTOBUF_NAMESPACE_ID::Syntax Api::syntax() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax)
  return _internal_syntax();
}
inline void Api::_internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) {
  
  _impl_.syntax_ = value;
}
inline void Api::set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) {
  _internal_set_syntax(value);
  // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
}

// -------------------------------------------------------------------

// Method

// string name = 1;
inline void Method::clear_name() {
  _impl_.name_.ClearToEmpty();
}
inline const std::string& Method::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
  return _internal_name();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Method::set_name(ArgT0&& arg0, ArgT... args) {
 
 _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
}
inline std::string* Method::mutable_name() {
  std::string* _s = _internal_mutable_name();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.name)
  return _s;
}
inline const std::string& Method::_internal_name() const {
  return _impl_.name_.Get();
}
inline void Method::_internal_set_name(const std::string& value) {
  
  _impl_.name_.Set(value, GetArenaForAllocation());
}
inline std::string* Method::_internal_mutable_name() {
  
  return _impl_.name_.Mutable(GetArenaForAllocation());
}
inline std::string* Method::release_name() {
  // @@protoc_insertion_point(field_release:google.protobuf.Method.name)
  return _impl_.name_.Release();
}
inline void Method::set_allocated_name(std::string* name) {
  if (name != nullptr) {
    
  } else {
    
  }
  _impl_.name_.SetAllocated(name, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.name_.IsDefault()) {
    _impl_.name_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
}

// string request_type_url = 2;
inline void Method::clear_request_type_url() {
  _impl_.request_type_url_.ClearToEmpty();
}
inline const std::string& Method::request_type_url() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
  return _internal_request_type_url();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Method::set_request_type_url(ArgT0&& arg0, ArgT... args) {
 
 _impl_.request_type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
}
inline std::string* Method::mutable_request_type_url() {
  std::string* _s = _internal_mutable_request_type_url();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.request_type_url)
  return _s;
}
inline const std::string& Method::_internal_request_type_url() const {
  return _impl_.request_type_url_.Get();
}
inline void Method::_internal_set_request_type_url(const std::string& value) {
  
  _impl_.request_type_url_.Set(value, GetArenaForAllocation());
}
inline std::string* Method::_internal_mutable_request_type_url() {
  
  return _impl_.request_type_url_.Mutable(GetArenaForAllocation());
}
inline std::string* Method::release_request_type_url() {
  // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url)
  return _impl_.request_type_url_.Release();
}
inline void Method::set_allocated_request_type_url(std::string* request_type_url) {
  if (request_type_url != nullptr) {
    
  } else {
    
  }
  _impl_.request_type_url_.SetAllocated(request_type_url, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.request_type_url_.IsDefault()) {
    _impl_.request_type_url_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
}

// bool request_streaming = 3;
inline void Method::clear_request_streaming() {
  _impl_.request_streaming_ = false;
}
inline bool Method::_internal_request_streaming() const {
  return _impl_.request_streaming_;
}
inline bool Method::request_streaming() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming)
  return _internal_request_streaming();
}
inline void Method::_internal_set_request_streaming(bool value) {
  
  _impl_.request_streaming_ = value;
}
inline void Method::set_request_streaming(bool value) {
  _internal_set_request_streaming(value);
  // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
}

// string response_type_url = 4;
inline void Method::clear_response_type_url() {
  _impl_.response_type_url_.ClearToEmpty();
}
inline const std::string& Method::response_type_url() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
  return _internal_response_type_url();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Method::set_response_type_url(ArgT0&& arg0, ArgT... args) {
 
 _impl_.response_type_url_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
}
inline std::string* Method::mutable_response_type_url() {
  std::string* _s = _internal_mutable_response_type_url();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.response_type_url)
  return _s;
}
inline const std::string& Method::_internal_response_type_url() const {
  return _impl_.response_type_url_.Get();
}
inline void Method::_internal_set_response_type_url(const std::string& value) {
  
  _impl_.response_type_url_.Set(value, GetArenaForAllocation());
}
inline std::string* Method::_internal_mutable_response_type_url() {
  
  return _impl_.response_type_url_.Mutable(GetArenaForAllocation());
}
inline std::string* Method::release_response_type_url() {
  // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url)
  return _impl_.response_type_url_.Release();
}
inline void Method::set_allocated_response_type_url(std::string* response_type_url) {
  if (response_type_url != nullptr) {
    
  } else {
    
  }
  _impl_.response_type_url_.SetAllocated(response_type_url, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.response_type_url_.IsDefault()) {
    _impl_.response_type_url_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
}

// bool response_streaming = 5;
inline void Method::clear_response_streaming() {
  _impl_.response_streaming_ = false;
}
inline bool Method::_internal_response_streaming() const {
  return _impl_.response_streaming_;
}
inline bool Method::response_streaming() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming)
  return _internal_response_streaming();
}
inline void Method::_internal_set_response_streaming(bool value) {
  
  _impl_.response_streaming_ = value;
}
inline void Method::set_response_streaming(bool value) {
  _internal_set_response_streaming(value);
  // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming)
}

// repeated .google.protobuf.Option options = 6;
inline int Method::_internal_options_size() const {
  return _impl_.options_.size();
}
inline int Method::options_size() const {
  return _internal_options_size();
}
inline ::PROTOBUF_NAMESPACE_ID::Option* Method::mutable_options(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
  return _impl_.options_.Mutable(index);
}
inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >*
Method::mutable_options() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
  return &_impl_.options_;
}
inline const ::PROTOBUF_NAMESPACE_ID::Option& Method::_internal_options(int index) const {
  return _impl_.options_.Get(index);
}
inline const ::PROTOBUF_NAMESPACE_ID::Option& Method::options(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.options)
  return _internal_options(index);
}
inline ::PROTOBUF_NAMESPACE_ID::Option* Method::_internal_add_options() {
  return _impl_.options_.Add();
}
inline ::PROTOBUF_NAMESPACE_ID::Option* Method::add_options() {
  ::PROTOBUF_NAMESPACE_ID::Option* _add = _internal_add_options();
  // @@protoc_insertion_point(field_add:google.protobuf.Method.options)
  return _add;
}
inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option >&
Method::options() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Method.options)
  return _impl_.options_;
}

// .google.protobuf.Syntax syntax = 7;
inline void Method::clear_syntax() {
  _impl_.syntax_ = 0;
}
inline ::PROTOBUF_NAMESPACE_ID::Syntax Method::_internal_syntax() const {
  return static_cast< ::PROTOBUF_NAMESPACE_ID::Syntax >(_impl_.syntax_);
}
inline ::PROTOBUF_NAMESPACE_ID::Syntax Method::syntax() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax)
  return _internal_syntax();
}
inline void Method::_internal_set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) {
  
  _impl_.syntax_ = value;
}
inline void Method::set_syntax(::PROTOBUF_NAMESPACE_ID::Syntax value) {
  _internal_set_syntax(value);
  // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
}

// -------------------------------------------------------------------

// Mixin

// string name = 1;
inline void Mixin::clear_name() {
  _impl_.name_.ClearToEmpty();
}
inline const std::string& Mixin::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
  return _internal_name();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Mixin::set_name(ArgT0&& arg0, ArgT... args) {
 
 _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
}
inline std::string* Mixin::mutable_name() {
  std::string* _s = _internal_mutable_name();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.name)
  return _s;
}
inline const std::string& Mixin::_internal_name() const {
  return _impl_.name_.Get();
}
inline void Mixin::_internal_set_name(const std::string& value) {
  
  _impl_.name_.Set(value, GetArenaForAllocation());
}
inline std::string* Mixin::_internal_mutable_name() {
  
  return _impl_.name_.Mutable(GetArenaForAllocation());
}
inline std::string* Mixin::release_name() {
  // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name)
  return _impl_.name_.Release();
}
inline void Mixin::set_allocated_name(std::string* name) {
  if (name != nullptr) {
    
  } else {
    
  }
  _impl_.name_.SetAllocated(name, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.name_.IsDefault()) {
    _impl_.name_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
}

// string root = 2;
inline void Mixin::clear_root() {
  _impl_.root_.ClearToEmpty();
}
inline const std::string& Mixin::root() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
  return _internal_root();
}
template <typename ArgT0, typename... ArgT>
inline PROTOBUF_ALWAYS_INLINE
void Mixin::set_root(ArgT0&& arg0, ArgT... args) {
 
 _impl_.root_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
  // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
}
inline std::string* Mixin::mutable_root() {
  std::string* _s = _internal_mutable_root();
  // @@protoc_insertion_point(field_mutable:google.protobuf.Mixin.root)
  return _s;
}
inline const std::string& Mixin::_internal_root() const {
  return _impl_.root_.Get();
}
inline void Mixin::_internal_set_root(const std::string& value) {
  
  _impl_.root_.Set(value, GetArenaForAllocation());
}
inline std::string* Mixin::_internal_mutable_root() {
  
  return _impl_.root_.Mutable(GetArenaForAllocation());
}
inline std::string* Mixin::release_root() {
  // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root)
  return _impl_.root_.Release();
}
inline void Mixin::set_allocated_root(std::string* root) {
  if (root != nullptr) {
    
  } else {
    
  }
  _impl_.root_.SetAllocated(root, GetArenaForAllocation());
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
  if (_impl_.root_.IsDefault()) {
    _impl_.root_.Set("", GetArenaForAllocation());
  }
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
}

#ifdef __GNUC__
  #pragma GCC diagnostic pop
#endif  // __GNUC__
// -------------------------------------------------------------------

// -------------------------------------------------------------------


// @@protoc_insertion_point(namespace_scope)

PROTOBUF_NAMESPACE_CLOSE

// @@protoc_insertion_point(global_scope)

#include <google/protobuf/port_undef.inc>
#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
