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

#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "google/protobuf/type.pb.h"

#include <algorithm>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)

namespace google {
namespace protobuf {

namespace {

const ::google::protobuf::Descriptor* Type_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Type_reflection_ = NULL;
const ::google::protobuf::Descriptor* Field_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Field_reflection_ = NULL;
const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor_ = NULL;
const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor_ = NULL;
const ::google::protobuf::Descriptor* Enum_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Enum_reflection_ = NULL;
const ::google::protobuf::Descriptor* EnumValue_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  EnumValue_reflection_ = NULL;
const ::google::protobuf::Descriptor* Option_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
  Option_reflection_ = NULL;

}  // namespace


void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() {
  protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  const ::google::protobuf::FileDescriptor* file =
    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
      "google/protobuf/type.proto");
  GOOGLE_CHECK(file != NULL);
  Type_descriptor_ = file->message_type(0);
  static const int Type_offsets_[5] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, name_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, fields_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, oneofs_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, options_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, source_context_),
  };
  Type_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Type_descriptor_,
      Type::default_instance_,
      Type_offsets_,
      -1,
      -1,
      -1,
      sizeof(Type),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _is_default_instance_));
  Field_descriptor_ = file->message_type(1);
  static const int Field_offsets_[8] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, kind_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, cardinality_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, number_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, name_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, type_url_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, oneof_index_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, packed_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, options_),
  };
  Field_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Field_descriptor_,
      Field::default_instance_,
      Field_offsets_,
      -1,
      -1,
      -1,
      sizeof(Field),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Field, _is_default_instance_));
  Field_Kind_descriptor_ = Field_descriptor_->enum_type(0);
  Field_Cardinality_descriptor_ = Field_descriptor_->enum_type(1);
  Enum_descriptor_ = file->message_type(2);
  static const int Enum_offsets_[4] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, name_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, enumvalue_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, options_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, source_context_),
  };
  Enum_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Enum_descriptor_,
      Enum::default_instance_,
      Enum_offsets_,
      -1,
      -1,
      -1,
      sizeof(Enum),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Enum, _is_default_instance_));
  EnumValue_descriptor_ = file->message_type(3);
  static const int EnumValue_offsets_[3] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, name_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, number_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, options_),
  };
  EnumValue_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      EnumValue_descriptor_,
      EnumValue::default_instance_,
      EnumValue_offsets_,
      -1,
      -1,
      -1,
      sizeof(EnumValue),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValue, _is_default_instance_));
  Option_descriptor_ = file->message_type(4);
  static const int Option_offsets_[2] = {
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, name_),
    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, value_),
  };
  Option_reflection_ =
    ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
      Option_descriptor_,
      Option::default_instance_,
      Option_offsets_,
      -1,
      -1,
      -1,
      sizeof(Option),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _internal_metadata_),
      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, _is_default_instance_));
}

namespace {

GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
inline void protobuf_AssignDescriptorsOnce() {
  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
                 &protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto);
}

void protobuf_RegisterTypes(const ::std::string&) {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Type_descriptor_, &Type::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Field_descriptor_, &Field::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Enum_descriptor_, &Enum::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      EnumValue_descriptor_, &EnumValue::default_instance());
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
      Option_descriptor_, &Option::default_instance());
}

}  // namespace

void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto() {
  delete Type::default_instance_;
  delete Type_reflection_;
  delete Field::default_instance_;
  delete Field_reflection_;
  delete Enum::default_instance_;
  delete Enum_reflection_;
  delete EnumValue::default_instance_;
  delete EnumValue_reflection_;
  delete Option::default_instance_;
  delete Option_reflection_;
}

void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() {
  static bool already_here = false;
  if (already_here) return;
  already_here = true;
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto();
  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
    "\n\032google/protobuf/type.proto\022\017google.pro"
    "tobuf\032\031google/protobuf/any.proto\032$google"
    "/protobuf/source_context.proto\"\256\001\n\004Type\022"
    "\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p"
    "rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options"
    "\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc"
    "e_context\030\005 \001(\0132\036.google.protobuf.Source"
    "Context\"\233\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.google"
    ".protobuf.Field.Kind\0227\n\013cardinality\030\002 \001("
    "\0162\".google.protobuf.Field.Cardinality\022\016\n"
    "\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url\030"
    "\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 \001"
    "(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.Op"
    "tion\"\270\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TYPE_"
    "DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003"
    "\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYP"
    "E_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BO"
    "OL\020\010\022\017\n\013TYPE_STRING\020\t\022\020\n\014TYPE_MESSAGE\020\013\022"
    "\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE"
    "_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXE"
    "D64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\""
    "t\n\013Cardinality\022\027\n\023CARDINALITY_UNKNOWN\020\000\022"
    "\030\n\024CARDINALITY_OPTIONAL\020\001\022\030\n\024CARDINALITY"
    "_REQUIRED\020\002\022\030\n\024CARDINALITY_REPEATED\020\003\"\245\001"
    "\n\004Enum\022\014\n\004name\030\001 \001(\t\022-\n\tenumvalue\030\002 \003(\0132"
    "\032.google.protobuf.EnumValue\022(\n\007options\030\003"
    " \003(\0132\027.google.protobuf.Option\0226\n\016source_"
    "context\030\004 \001(\0132\036.google.protobuf.SourceCo"
    "ntext\"S\n\tEnumValue\022\014\n\004name\030\001 \001(\t\022\016\n\006numb"
    "er\030\002 \001(\005\022(\n\007options\030\003 \003(\0132\027.google.proto"
    "buf.Option\";\n\006Option\022\014\n\004name\030\001 \001(\t\022#\n\005va"
    "lue\030\002 \001(\0132\024.google.protobuf.AnyB(\n\023com.g"
    "oogle.protobufB\tTypeProtoP\001\242\002\003GPBb\006proto"
    "3", 1321);
  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
    "google/protobuf/type.proto", &protobuf_RegisterTypes);
  Type::default_instance_ = new Type();
  Field::default_instance_ = new Field();
  Enum::default_instance_ = new Enum();
  EnumValue::default_instance_ = new EnumValue();
  Option::default_instance_ = new Option();
  Type::default_instance_->InitAsDefaultInstance();
  Field::default_instance_->InitAsDefaultInstance();
  Enum::default_instance_->InitAsDefaultInstance();
  EnumValue::default_instance_->InitAsDefaultInstance();
  Option::default_instance_->InitAsDefaultInstance();
  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto);
}

// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto {
  StaticDescriptorInitializer_google_2fprotobuf_2ftype_2eproto() {
    protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  }
} static_descriptor_initializer_google_2fprotobuf_2ftype_2eproto_;

namespace {

static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
static void MergeFromFail(int line) {
  GOOGLE_CHECK(false) << __FILE__ << ":" << line;
}

}  // namespace


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

#ifndef _MSC_VER
const int Type::kNameFieldNumber;
const int Type::kFieldsFieldNumber;
const int Type::kOneofsFieldNumber;
const int Type::kOptionsFieldNumber;
const int Type::kSourceContextFieldNumber;
#endif  // !_MSC_VER

Type::Type()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:google.protobuf.Type)
}

void Type::InitAsDefaultInstance() {
  _is_default_instance_ = true;
  source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
}

Type::Type(const Type& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:google.protobuf.Type)
}

void Type::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  source_context_ = NULL;
}

Type::~Type() {
  // @@protoc_insertion_point(destructor:google.protobuf.Type)
  SharedDtor();
}

void Type::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
    delete source_context_;
  }
}

void Type::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Type::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Type_descriptor_;
}

const Type& Type::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  return *default_instance_;
}

Type* Type::default_instance_ = NULL;

Type* Type::New(::google::protobuf::Arena* arena) const {
  Type* n = new Type;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Type::Clear() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
  source_context_ = NULL;
  fields_.Clear();
  oneofs_.Clear();
  options_.Clear();
}

bool Type::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:google.protobuf.Type)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string name = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.Type.name");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_fields;
        break;
      }

      // repeated .google.protobuf.Field fields = 2;
      case 2: {
        if (tag == 18) {
         parse_fields:
          DO_(input->IncrementRecursionDepth());
         parse_loop_fields:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_fields()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_loop_fields;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectTag(26)) goto parse_oneofs;
        break;
      }

      // repeated string oneofs = 3;
      case 3: {
        if (tag == 26) {
         parse_oneofs:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->add_oneofs()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->oneofs(this->oneofs_size() - 1).data(),
            this->oneofs(this->oneofs_size() - 1).length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.Type.oneofs");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(26)) goto parse_oneofs;
        if (input->ExpectTag(34)) goto parse_options;
        break;
      }

      // repeated .google.protobuf.Option options = 4;
      case 4: {
        if (tag == 34) {
         parse_options:
          DO_(input->IncrementRecursionDepth());
         parse_loop_options:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_options()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(34)) goto parse_loop_options;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectTag(42)) goto parse_source_context;
        break;
      }

      // optional .google.protobuf.SourceContext source_context = 5;
      case 5: {
        if (tag == 42) {
         parse_source_context:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_source_context()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:google.protobuf.Type)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:google.protobuf.Type)
  return false;
#undef DO_
}

void Type::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:google.protobuf.Type)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Type.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->name(), output);
  }

  // repeated .google.protobuf.Field fields = 2;
  for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, this->fields(i), output);
  }

  // repeated string oneofs = 3;
  for (int i = 0; i < this->oneofs_size(); i++) {
  ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
    this->oneofs(i).data(), this->oneofs(i).length(),
    ::google::protobuf::internal::WireFormat::SERIALIZE,
    "google.protobuf.Type.oneofs");
    ::google::protobuf::internal::WireFormatLite::WriteString(
      3, this->oneofs(i), output);
  }

  // repeated .google.protobuf.Option options = 4;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      4, this->options(i), output);
  }

  // optional .google.protobuf.SourceContext source_context = 5;
  if (this->has_source_context()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      5, *this->source_context_, output);
  }

  // @@protoc_insertion_point(serialize_end:google.protobuf.Type)
}

::google::protobuf::uint8* Type::SerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Type.name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        1, this->name(), target);
  }

  // repeated .google.protobuf.Field fields = 2;
  for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        2, this->fields(i), target);
  }

  // repeated string oneofs = 3;
  for (int i = 0; i < this->oneofs_size(); i++) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->oneofs(i).data(), this->oneofs(i).length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Type.oneofs");
    target = ::google::protobuf::internal::WireFormatLite::
      WriteStringToArray(3, this->oneofs(i), target);
  }

  // repeated .google.protobuf.Option options = 4;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        4, this->options(i), target);
  }

  // optional .google.protobuf.SourceContext source_context = 5;
  if (this->has_source_context()) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        5, *this->source_context_, target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type)
  return target;
}

int Type::ByteSize() const {
  int total_size = 0;

  // optional string name = 1;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional .google.protobuf.SourceContext source_context = 5;
  if (this->has_source_context()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->source_context_);
  }

  // repeated .google.protobuf.Field fields = 2;
  total_size += 1 * this->fields_size();
  for (int i = 0; i < this->fields_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->fields(i));
  }

  // repeated string oneofs = 3;
  total_size += 1 * this->oneofs_size();
  for (int i = 0; i < this->oneofs_size(); i++) {
    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
      this->oneofs(i));
  }

  // repeated .google.protobuf.Option options = 4;
  total_size += 1 * this->options_size();
  for (int i = 0; i < this->options_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->options(i));
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Type::MergeFrom(const ::google::protobuf::Message& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  const Type* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Type>(
          &from);
  if (source == NULL) {
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
    MergeFrom(*source);
  }
}

void Type::MergeFrom(const Type& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  fields_.MergeFrom(from.fields_);
  oneofs_.MergeFrom(from.oneofs_);
  options_.MergeFrom(from.options_);
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.has_source_context()) {
    mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
  }
}

void Type::CopyFrom(const ::google::protobuf::Message& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Type::CopyFrom(const Type& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Type::IsInitialized() const {

  return true;
}

void Type::Swap(Type* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Type::InternalSwap(Type* other) {
  name_.Swap(&other->name_);
  fields_.UnsafeArenaSwap(&other->fields_);
  oneofs_.UnsafeArenaSwap(&other->oneofs_);
  options_.UnsafeArenaSwap(&other->options_);
  std::swap(source_context_, other->source_context_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Type::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Type_descriptor_;
  metadata.reflection = Type_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Type

// optional string name = 1;
void Type::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Type::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Type::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
}
 void Type::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
}
 void Type::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
}
 ::std::string* Type::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Type::release_name() {
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Type::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.name)
}

// repeated .google.protobuf.Field fields = 2;
int Type::fields_size() const {
  return fields_.size();
}
void Type::clear_fields() {
  fields_.Clear();
}
 const ::google::protobuf::Field& Type::fields(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Type.fields)
  return fields_.Get(index);
}
 ::google::protobuf::Field* Type::mutable_fields(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.fields)
  return fields_.Mutable(index);
}
 ::google::protobuf::Field* Type::add_fields() {
  // @@protoc_insertion_point(field_add:google.protobuf.Type.fields)
  return fields_.Add();
}
 const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >&
Type::fields() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Type.fields)
  return fields_;
}
 ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field >*
Type::mutable_fields() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.fields)
  return &fields_;
}

// repeated string oneofs = 3;
int Type::oneofs_size() const {
  return oneofs_.size();
}
void Type::clear_oneofs() {
  oneofs_.Clear();
}
 const ::std::string& Type::oneofs(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Type.oneofs)
  return oneofs_.Get(index);
}
 ::std::string* Type::mutable_oneofs(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.oneofs)
  return oneofs_.Mutable(index);
}
 void Type::set_oneofs(int index, const ::std::string& value) {
  // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
  oneofs_.Mutable(index)->assign(value);
}
 void Type::set_oneofs(int index, const char* value) {
  oneofs_.Mutable(index)->assign(value);
  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs)
}
 void Type::set_oneofs(int index, const char* value, size_t size) {
  oneofs_.Mutable(index)->assign(
    reinterpret_cast<const char*>(value), size);
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
}
 ::std::string* Type::add_oneofs() {
  return oneofs_.Add();
}
 void Type::add_oneofs(const ::std::string& value) {
  oneofs_.Add()->assign(value);
  // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs)
}
 void Type::add_oneofs(const char* value) {
  oneofs_.Add()->assign(value);
  // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs)
}
 void Type::add_oneofs(const char* value, size_t size) {
  oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size);
  // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs)
}
 const ::google::protobuf::RepeatedPtrField< ::std::string>&
Type::oneofs() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Type.oneofs)
  return oneofs_;
}
 ::google::protobuf::RepeatedPtrField< ::std::string>*
Type::mutable_oneofs() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.oneofs)
  return &oneofs_;
}

// repeated .google.protobuf.Option options = 4;
int Type::options_size() const {
  return options_.size();
}
void Type::clear_options() {
  options_.Clear();
}
 const ::google::protobuf::Option& Type::options(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Type.options)
  return options_.Get(index);
}
 ::google::protobuf::Option* Type::mutable_options(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.options)
  return options_.Mutable(index);
}
 ::google::protobuf::Option* Type::add_options() {
  // @@protoc_insertion_point(field_add:google.protobuf.Type.options)
  return options_.Add();
}
 const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Type::options() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Type.options)
  return options_;
}
 ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Type::mutable_options() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Type.options)
  return &options_;
}

// optional .google.protobuf.SourceContext source_context = 5;
bool Type::has_source_context() const {
  return !_is_default_instance_ && source_context_ != NULL;
}
void Type::clear_source_context() {
  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
  source_context_ = NULL;
}
 const ::google::protobuf::SourceContext& Type::source_context() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
}
 ::google::protobuf::SourceContext* Type::mutable_source_context() {
  
  if (source_context_ == NULL) {
    source_context_ = new ::google::protobuf::SourceContext;
  }
  // @@protoc_insertion_point(field_mutable:google.protobuf.Type.source_context)
  return source_context_;
}
 ::google::protobuf::SourceContext* Type::release_source_context() {
  
  ::google::protobuf::SourceContext* temp = source_context_;
  source_context_ = NULL;
  return temp;
}
 void Type::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
  delete source_context_;
  source_context_ = source_context;
  if (source_context) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

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

const ::google::protobuf::EnumDescriptor* Field_Kind_descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Field_Kind_descriptor_;
}
bool Field_Kind_IsValid(int value) {
  switch(value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
    case 17:
    case 18:
      return true;
    default:
      return false;
  }
}

#ifndef _MSC_VER
const Field_Kind Field::TYPE_UNKNOWN;
const Field_Kind Field::TYPE_DOUBLE;
const Field_Kind Field::TYPE_FLOAT;
const Field_Kind Field::TYPE_INT64;
const Field_Kind Field::TYPE_UINT64;
const Field_Kind Field::TYPE_INT32;
const Field_Kind Field::TYPE_FIXED64;
const Field_Kind Field::TYPE_FIXED32;
const Field_Kind Field::TYPE_BOOL;
const Field_Kind Field::TYPE_STRING;
const Field_Kind Field::TYPE_MESSAGE;
const Field_Kind Field::TYPE_BYTES;
const Field_Kind Field::TYPE_UINT32;
const Field_Kind Field::TYPE_ENUM;
const Field_Kind Field::TYPE_SFIXED32;
const Field_Kind Field::TYPE_SFIXED64;
const Field_Kind Field::TYPE_SINT32;
const Field_Kind Field::TYPE_SINT64;
const Field_Kind Field::Kind_MIN;
const Field_Kind Field::Kind_MAX;
const int Field::Kind_ARRAYSIZE;
#endif  // _MSC_VER
const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Field_Cardinality_descriptor_;
}
bool Field_Cardinality_IsValid(int value) {
  switch(value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    default:
      return false;
  }
}

#ifndef _MSC_VER
const Field_Cardinality Field::CARDINALITY_UNKNOWN;
const Field_Cardinality Field::CARDINALITY_OPTIONAL;
const Field_Cardinality Field::CARDINALITY_REQUIRED;
const Field_Cardinality Field::CARDINALITY_REPEATED;
const Field_Cardinality Field::Cardinality_MIN;
const Field_Cardinality Field::Cardinality_MAX;
const int Field::Cardinality_ARRAYSIZE;
#endif  // _MSC_VER
#ifndef _MSC_VER
const int Field::kKindFieldNumber;
const int Field::kCardinalityFieldNumber;
const int Field::kNumberFieldNumber;
const int Field::kNameFieldNumber;
const int Field::kTypeUrlFieldNumber;
const int Field::kOneofIndexFieldNumber;
const int Field::kPackedFieldNumber;
const int Field::kOptionsFieldNumber;
#endif  // !_MSC_VER

Field::Field()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:google.protobuf.Field)
}

void Field::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

Field::Field(const Field& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:google.protobuf.Field)
}

void Field::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  kind_ = 0;
  cardinality_ = 0;
  number_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  oneof_index_ = 0;
  packed_ = false;
}

Field::~Field() {
  // @@protoc_insertion_point(destructor:google.protobuf.Field)
  SharedDtor();
}

void Field::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  type_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
  }
}

void Field::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Field::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Field_descriptor_;
}

const Field& Field::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  return *default_instance_;
}

Field* Field::default_instance_ = NULL;

Field* Field::New(::google::protobuf::Arena* arena) const {
  Field* n = new Field;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Field::Clear() {
#define ZR_HELPER_(f) reinterpret_cast<char*>(\
  &reinterpret_cast<Field*>(16)->f)

#define ZR_(first, last) do {\
  ::memset(&first, 0,\
           ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)

  ZR_(kind_, cardinality_);
  ZR_(number_, oneof_index_);
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  packed_ = false;

#undef ZR_HELPER_
#undef ZR_

  options_.Clear();
}

bool Field::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:google.protobuf.Field)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional .google.protobuf.Field.Kind kind = 1;
      case 1: {
        if (tag == 8) {
          int value;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_kind(static_cast< ::google::protobuf::Field_Kind >(value));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(16)) goto parse_cardinality;
        break;
      }

      // optional .google.protobuf.Field.Cardinality cardinality = 2;
      case 2: {
        if (tag == 16) {
         parse_cardinality:
          int value;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_cardinality(static_cast< ::google::protobuf::Field_Cardinality >(value));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(24)) goto parse_number;
        break;
      }

      // optional int32 number = 3;
      case 3: {
        if (tag == 24) {
         parse_number:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &number_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(34)) goto parse_name;
        break;
      }

      // optional string name = 4;
      case 4: {
        if (tag == 34) {
         parse_name:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.Field.name");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(50)) goto parse_type_url;
        break;
      }

      // optional string type_url = 6;
      case 6: {
        if (tag == 50) {
         parse_type_url:
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_type_url()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->type_url().data(), this->type_url().length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.Field.type_url");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(56)) goto parse_oneof_index;
        break;
      }

      // optional int32 oneof_index = 7;
      case 7: {
        if (tag == 56) {
         parse_oneof_index:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &oneof_index_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(64)) goto parse_packed;
        break;
      }

      // optional bool packed = 8;
      case 8: {
        if (tag == 64) {
         parse_packed:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                 input, &packed_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(74)) goto parse_options;
        break;
      }

      // repeated .google.protobuf.Option options = 9;
      case 9: {
        if (tag == 74) {
         parse_options:
          DO_(input->IncrementRecursionDepth());
         parse_loop_options:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_options()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(74)) goto parse_loop_options;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:google.protobuf.Field)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:google.protobuf.Field)
  return false;
#undef DO_
}

void Field::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:google.protobuf.Field)
  // optional .google.protobuf.Field.Kind kind = 1;
  if (this->kind() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->kind(), output);
  }

  // optional .google.protobuf.Field.Cardinality cardinality = 2;
  if (this->cardinality() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->cardinality(), output);
  }

  // optional int32 number = 3;
  if (this->number() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
  }

  // optional string name = 4;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Field.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      4, this->name(), output);
  }

  // optional string type_url = 6;
  if (this->type_url().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->type_url().data(), this->type_url().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Field.type_url");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      6, this->type_url(), output);
  }

  // optional int32 oneof_index = 7;
  if (this->oneof_index() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(7, this->oneof_index(), output);
  }

  // optional bool packed = 8;
  if (this->packed() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteBool(8, this->packed(), output);
  }

  // repeated .google.protobuf.Option options = 9;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      9, this->options(i), output);
  }

  // @@protoc_insertion_point(serialize_end:google.protobuf.Field)
}

::google::protobuf::uint8* Field::SerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field)
  // optional .google.protobuf.Field.Kind kind = 1;
  if (this->kind() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->kind(), target);
  }

  // optional .google.protobuf.Field.Cardinality cardinality = 2;
  if (this->cardinality() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->cardinality(), target);
  }

  // optional int32 number = 3;
  if (this->number() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
  }

  // optional string name = 4;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Field.name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        4, this->name(), target);
  }

  // optional string type_url = 6;
  if (this->type_url().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->type_url().data(), this->type_url().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Field.type_url");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        6, this->type_url(), target);
  }

  // optional int32 oneof_index = 7;
  if (this->oneof_index() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(7, this->oneof_index(), target);
  }

  // optional bool packed = 8;
  if (this->packed() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(8, this->packed(), target);
  }

  // repeated .google.protobuf.Option options = 9;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        9, this->options(i), target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field)
  return target;
}

int Field::ByteSize() const {
  int total_size = 0;

  // optional .google.protobuf.Field.Kind kind = 1;
  if (this->kind() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->kind());
  }

  // optional .google.protobuf.Field.Cardinality cardinality = 2;
  if (this->cardinality() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->cardinality());
  }

  // optional int32 number = 3;
  if (this->number() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->number());
  }

  // optional string name = 4;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional string type_url = 6;
  if (this->type_url().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->type_url());
  }

  // optional int32 oneof_index = 7;
  if (this->oneof_index() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->oneof_index());
  }

  // optional bool packed = 8;
  if (this->packed() != 0) {
    total_size += 1 + 1;
  }

  // repeated .google.protobuf.Option options = 9;
  total_size += 1 * this->options_size();
  for (int i = 0; i < this->options_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->options(i));
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Field::MergeFrom(const ::google::protobuf::Message& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  const Field* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Field>(
          &from);
  if (source == NULL) {
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
    MergeFrom(*source);
  }
}

void Field::MergeFrom(const Field& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  options_.MergeFrom(from.options_);
  if (from.kind() != 0) {
    set_kind(from.kind());
  }
  if (from.cardinality() != 0) {
    set_cardinality(from.cardinality());
  }
  if (from.number() != 0) {
    set_number(from.number());
  }
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.type_url().size() > 0) {

    type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
  }
  if (from.oneof_index() != 0) {
    set_oneof_index(from.oneof_index());
  }
  if (from.packed() != 0) {
    set_packed(from.packed());
  }
}

void Field::CopyFrom(const ::google::protobuf::Message& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Field::CopyFrom(const Field& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Field::IsInitialized() const {

  return true;
}

void Field::Swap(Field* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Field::InternalSwap(Field* other) {
  std::swap(kind_, other->kind_);
  std::swap(cardinality_, other->cardinality_);
  std::swap(number_, other->number_);
  name_.Swap(&other->name_);
  type_url_.Swap(&other->type_url_);
  std::swap(oneof_index_, other->oneof_index_);
  std::swap(packed_, other->packed_);
  options_.UnsafeArenaSwap(&other->options_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Field::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Field_descriptor_;
  metadata.reflection = Field_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Field

// optional .google.protobuf.Field.Kind kind = 1;
void Field::clear_kind() {
  kind_ = 0;
}
 ::google::protobuf::Field_Kind Field::kind() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.kind)
  return static_cast< ::google::protobuf::Field_Kind >(kind_);
}
 void Field::set_kind(::google::protobuf::Field_Kind value) {
  
  kind_ = value;
  // @@protoc_insertion_point(field_set:google.protobuf.Field.kind)
}

// optional .google.protobuf.Field.Cardinality cardinality = 2;
void Field::clear_cardinality() {
  cardinality_ = 0;
}
 ::google::protobuf::Field_Cardinality Field::cardinality() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.cardinality)
  return static_cast< ::google::protobuf::Field_Cardinality >(cardinality_);
}
 void Field::set_cardinality(::google::protobuf::Field_Cardinality value) {
  
  cardinality_ = value;
  // @@protoc_insertion_point(field_set:google.protobuf.Field.cardinality)
}

// optional int32 number = 3;
void Field::clear_number() {
  number_ = 0;
}
 ::google::protobuf::int32 Field::number() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.number)
  return number_;
}
 void Field::set_number(::google::protobuf::int32 value) {
  
  number_ = value;
  // @@protoc_insertion_point(field_set:google.protobuf.Field.number)
}

// optional string name = 4;
void Field::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Field::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Field::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
}
 void Field::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
}
 void Field::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
}
 ::std::string* Field::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Field::release_name() {
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Field::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.name)
}

// optional string type_url = 6;
void Field::clear_type_url() {
  type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Field::type_url() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
  return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Field::set_type_url(const ::std::string& value) {
  
  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
}
 void Field::set_type_url(const char* value) {
  
  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
}
 void Field::set_type_url(const char* value, size_t size) {
  
  type_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
}
 ::std::string* Field::mutable_type_url() {
  
  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.type_url)
  return type_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Field::release_type_url() {
  
  return type_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Field::set_allocated_type_url(::std::string* type_url) {
  if (type_url != NULL) {
    
  } else {
    
  }
  type_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_url);
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Field.type_url)
}

// optional int32 oneof_index = 7;
void Field::clear_oneof_index() {
  oneof_index_ = 0;
}
 ::google::protobuf::int32 Field::oneof_index() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index)
  return oneof_index_;
}
 void Field::set_oneof_index(::google::protobuf::int32 value) {
  
  oneof_index_ = value;
  // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index)
}

// optional bool packed = 8;
void Field::clear_packed() {
  packed_ = false;
}
 bool Field::packed() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.packed)
  return packed_;
}
 void Field::set_packed(bool value) {
  
  packed_ = value;
  // @@protoc_insertion_point(field_set:google.protobuf.Field.packed)
}

// repeated .google.protobuf.Option options = 9;
int Field::options_size() const {
  return options_.size();
}
void Field::clear_options() {
  options_.Clear();
}
 const ::google::protobuf::Option& Field::options(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Field.options)
  return options_.Get(index);
}
 ::google::protobuf::Option* Field::mutable_options(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Field.options)
  return options_.Mutable(index);
}
 ::google::protobuf::Option* Field::add_options() {
  // @@protoc_insertion_point(field_add:google.protobuf.Field.options)
  return options_.Add();
}
 const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Field::options() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Field.options)
  return options_;
}
 ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Field::mutable_options() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Field.options)
  return &options_;
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

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

#ifndef _MSC_VER
const int Enum::kNameFieldNumber;
const int Enum::kEnumvalueFieldNumber;
const int Enum::kOptionsFieldNumber;
const int Enum::kSourceContextFieldNumber;
#endif  // !_MSC_VER

Enum::Enum()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:google.protobuf.Enum)
}

void Enum::InitAsDefaultInstance() {
  _is_default_instance_ = true;
  source_context_ = const_cast< ::google::protobuf::SourceContext*>(&::google::protobuf::SourceContext::default_instance());
}

Enum::Enum(const Enum& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:google.protobuf.Enum)
}

void Enum::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  source_context_ = NULL;
}

Enum::~Enum() {
  // @@protoc_insertion_point(destructor:google.protobuf.Enum)
  SharedDtor();
}

void Enum::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
    delete source_context_;
  }
}

void Enum::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Enum::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Enum_descriptor_;
}

const Enum& Enum::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  return *default_instance_;
}

Enum* Enum::default_instance_ = NULL;

Enum* Enum::New(::google::protobuf::Arena* arena) const {
  Enum* n = new Enum;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Enum::Clear() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
  source_context_ = NULL;
  enumvalue_.Clear();
  options_.Clear();
}

bool Enum::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:google.protobuf.Enum)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string name = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.Enum.name");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_enumvalue;
        break;
      }

      // repeated .google.protobuf.EnumValue enumvalue = 2;
      case 2: {
        if (tag == 18) {
         parse_enumvalue:
          DO_(input->IncrementRecursionDepth());
         parse_loop_enumvalue:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_enumvalue()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_loop_enumvalue;
        if (input->ExpectTag(26)) goto parse_loop_options;
        input->UnsafeDecrementRecursionDepth();
        break;
      }

      // repeated .google.protobuf.Option options = 3;
      case 3: {
        if (tag == 26) {
          DO_(input->IncrementRecursionDepth());
         parse_loop_options:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_options()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(26)) goto parse_loop_options;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectTag(34)) goto parse_source_context;
        break;
      }

      // optional .google.protobuf.SourceContext source_context = 4;
      case 4: {
        if (tag == 34) {
         parse_source_context:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_source_context()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:google.protobuf.Enum)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:google.protobuf.Enum)
  return false;
#undef DO_
}

void Enum::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:google.protobuf.Enum)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Enum.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->name(), output);
  }

  // repeated .google.protobuf.EnumValue enumvalue = 2;
  for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, this->enumvalue(i), output);
  }

  // repeated .google.protobuf.Option options = 3;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      3, this->options(i), output);
  }

  // optional .google.protobuf.SourceContext source_context = 4;
  if (this->has_source_context()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      4, *this->source_context_, output);
  }

  // @@protoc_insertion_point(serialize_end:google.protobuf.Enum)
}

::google::protobuf::uint8* Enum::SerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Enum.name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        1, this->name(), target);
  }

  // repeated .google.protobuf.EnumValue enumvalue = 2;
  for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        2, this->enumvalue(i), target);
  }

  // repeated .google.protobuf.Option options = 3;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        3, this->options(i), target);
  }

  // optional .google.protobuf.SourceContext source_context = 4;
  if (this->has_source_context()) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        4, *this->source_context_, target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum)
  return target;
}

int Enum::ByteSize() const {
  int total_size = 0;

  // optional string name = 1;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional .google.protobuf.SourceContext source_context = 4;
  if (this->has_source_context()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->source_context_);
  }

  // repeated .google.protobuf.EnumValue enumvalue = 2;
  total_size += 1 * this->enumvalue_size();
  for (int i = 0; i < this->enumvalue_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->enumvalue(i));
  }

  // repeated .google.protobuf.Option options = 3;
  total_size += 1 * this->options_size();
  for (int i = 0; i < this->options_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->options(i));
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Enum::MergeFrom(const ::google::protobuf::Message& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  const Enum* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
          &from);
  if (source == NULL) {
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
    MergeFrom(*source);
  }
}

void Enum::MergeFrom(const Enum& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  enumvalue_.MergeFrom(from.enumvalue_);
  options_.MergeFrom(from.options_);
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.has_source_context()) {
    mutable_source_context()->::google::protobuf::SourceContext::MergeFrom(from.source_context());
  }
}

void Enum::CopyFrom(const ::google::protobuf::Message& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Enum::CopyFrom(const Enum& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Enum::IsInitialized() const {

  return true;
}

void Enum::Swap(Enum* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Enum::InternalSwap(Enum* other) {
  name_.Swap(&other->name_);
  enumvalue_.UnsafeArenaSwap(&other->enumvalue_);
  options_.UnsafeArenaSwap(&other->options_);
  std::swap(source_context_, other->source_context_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Enum::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Enum_descriptor_;
  metadata.reflection = Enum_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Enum

// optional string name = 1;
void Enum::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Enum::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Enum::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
}
 void Enum::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
}
 void Enum::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
}
 ::std::string* Enum::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Enum::release_name() {
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Enum::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.name)
}

// repeated .google.protobuf.EnumValue enumvalue = 2;
int Enum::enumvalue_size() const {
  return enumvalue_.size();
}
void Enum::clear_enumvalue() {
  enumvalue_.Clear();
}
 const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Enum.enumvalue)
  return enumvalue_.Get(index);
}
 ::google::protobuf::EnumValue* Enum::mutable_enumvalue(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.enumvalue)
  return enumvalue_.Mutable(index);
}
 ::google::protobuf::EnumValue* Enum::add_enumvalue() {
  // @@protoc_insertion_point(field_add:google.protobuf.Enum.enumvalue)
  return enumvalue_.Add();
}
 const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >&
Enum::enumvalue() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Enum.enumvalue)
  return enumvalue_;
}
 ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue >*
Enum::mutable_enumvalue() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.enumvalue)
  return &enumvalue_;
}

// repeated .google.protobuf.Option options = 3;
int Enum::options_size() const {
  return options_.size();
}
void Enum::clear_options() {
  options_.Clear();
}
 const ::google::protobuf::Option& Enum::options(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.Enum.options)
  return options_.Get(index);
}
 ::google::protobuf::Option* Enum::mutable_options(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.options)
  return options_.Mutable(index);
}
 ::google::protobuf::Option* Enum::add_options() {
  // @@protoc_insertion_point(field_add:google.protobuf.Enum.options)
  return options_.Add();
}
 const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
Enum::options() const {
  // @@protoc_insertion_point(field_list:google.protobuf.Enum.options)
  return options_;
}
 ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
Enum::mutable_options() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.Enum.options)
  return &options_;
}

// optional .google.protobuf.SourceContext source_context = 4;
bool Enum::has_source_context() const {
  return !_is_default_instance_ && source_context_ != NULL;
}
void Enum::clear_source_context() {
  if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
  source_context_ = NULL;
}
 const ::google::protobuf::SourceContext& Enum::source_context() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
  return source_context_ != NULL ? *source_context_ : *default_instance_->source_context_;
}
 ::google::protobuf::SourceContext* Enum::mutable_source_context() {
  
  if (source_context_ == NULL) {
    source_context_ = new ::google::protobuf::SourceContext;
  }
  // @@protoc_insertion_point(field_mutable:google.protobuf.Enum.source_context)
  return source_context_;
}
 ::google::protobuf::SourceContext* Enum::release_source_context() {
  
  ::google::protobuf::SourceContext* temp = source_context_;
  source_context_ = NULL;
  return temp;
}
 void Enum::set_allocated_source_context(::google::protobuf::SourceContext* source_context) {
  delete source_context_;
  source_context_ = source_context;
  if (source_context) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

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

#ifndef _MSC_VER
const int EnumValue::kNameFieldNumber;
const int EnumValue::kNumberFieldNumber;
const int EnumValue::kOptionsFieldNumber;
#endif  // !_MSC_VER

EnumValue::EnumValue()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:google.protobuf.EnumValue)
}

void EnumValue::InitAsDefaultInstance() {
  _is_default_instance_ = true;
}

EnumValue::EnumValue(const EnumValue& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValue)
}

void EnumValue::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  number_ = 0;
}

EnumValue::~EnumValue() {
  // @@protoc_insertion_point(destructor:google.protobuf.EnumValue)
  SharedDtor();
}

void EnumValue::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
  }
}

void EnumValue::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* EnumValue::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return EnumValue_descriptor_;
}

const EnumValue& EnumValue::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  return *default_instance_;
}

EnumValue* EnumValue::default_instance_ = NULL;

EnumValue* EnumValue::New(::google::protobuf::Arena* arena) const {
  EnumValue* n = new EnumValue;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void EnumValue::Clear() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  number_ = 0;
  options_.Clear();
}

bool EnumValue::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:google.protobuf.EnumValue)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string name = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.EnumValue.name");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(16)) goto parse_number;
        break;
      }

      // optional int32 number = 2;
      case 2: {
        if (tag == 16) {
         parse_number:
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                 input, &number_)));

        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(26)) goto parse_options;
        break;
      }

      // repeated .google.protobuf.Option options = 3;
      case 3: {
        if (tag == 26) {
         parse_options:
          DO_(input->IncrementRecursionDepth());
         parse_loop_options:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
                input, add_options()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(26)) goto parse_loop_options;
        input->UnsafeDecrementRecursionDepth();
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:google.protobuf.EnumValue)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValue)
  return false;
#undef DO_
}

void EnumValue::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValue)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.EnumValue.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->name(), output);
  }

  // optional int32 number = 2;
  if (this->number() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
  }

  // repeated .google.protobuf.Option options = 3;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      3, this->options(i), output);
  }

  // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValue)
}

::google::protobuf::uint8* EnumValue::SerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.EnumValue.name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        1, this->name(), target);
  }

  // optional int32 number = 2;
  if (this->number() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
  }

  // repeated .google.protobuf.Option options = 3;
  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        3, this->options(i), target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue)
  return target;
}

int EnumValue::ByteSize() const {
  int total_size = 0;

  // optional string name = 1;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional int32 number = 2;
  if (this->number() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::Int32Size(
        this->number());
  }

  // repeated .google.protobuf.Option options = 3;
  total_size += 1 * this->options_size();
  for (int i = 0; i < this->options_size(); i++) {
    total_size +=
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        this->options(i));
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  const EnumValue* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
          &from);
  if (source == NULL) {
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
    MergeFrom(*source);
  }
}

void EnumValue::MergeFrom(const EnumValue& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  options_.MergeFrom(from.options_);
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.number() != 0) {
    set_number(from.number());
  }
}

void EnumValue::CopyFrom(const ::google::protobuf::Message& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void EnumValue::CopyFrom(const EnumValue& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool EnumValue::IsInitialized() const {

  return true;
}

void EnumValue::Swap(EnumValue* other) {
  if (other == this) return;
  InternalSwap(other);
}
void EnumValue::InternalSwap(EnumValue* other) {
  name_.Swap(&other->name_);
  std::swap(number_, other->number_);
  options_.UnsafeArenaSwap(&other->options_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata EnumValue::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = EnumValue_descriptor_;
  metadata.reflection = EnumValue_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// EnumValue

// optional string name = 1;
void EnumValue::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& EnumValue::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void EnumValue::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
}
 void EnumValue::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
}
 void EnumValue::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
}
 ::std::string* EnumValue::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* EnumValue::release_name() {
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void EnumValue::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValue.name)
}

// optional int32 number = 2;
void EnumValue::clear_number() {
  number_ = 0;
}
 ::google::protobuf::int32 EnumValue::number() const {
  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number)
  return number_;
}
 void EnumValue::set_number(::google::protobuf::int32 value) {
  
  number_ = value;
  // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number)
}

// repeated .google.protobuf.Option options = 3;
int EnumValue::options_size() const {
  return options_.size();
}
void EnumValue::clear_options() {
  options_.Clear();
}
 const ::google::protobuf::Option& EnumValue::options(int index) const {
  // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.options)
  return options_.Get(index);
}
 ::google::protobuf::Option* EnumValue::mutable_options(int index) {
  // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValue.options)
  return options_.Mutable(index);
}
 ::google::protobuf::Option* EnumValue::add_options() {
  // @@protoc_insertion_point(field_add:google.protobuf.EnumValue.options)
  return options_.Add();
}
 const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
EnumValue::options() const {
  // @@protoc_insertion_point(field_list:google.protobuf.EnumValue.options)
  return options_;
}
 ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
EnumValue::mutable_options() {
  // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValue.options)
  return &options_;
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

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

#ifndef _MSC_VER
const int Option::kNameFieldNumber;
const int Option::kValueFieldNumber;
#endif  // !_MSC_VER

Option::Option()
  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:google.protobuf.Option)
}

void Option::InitAsDefaultInstance() {
  _is_default_instance_ = true;
  value_ = const_cast< ::google::protobuf::Any*>(&::google::protobuf::Any::default_instance());
}

Option::Option(const Option& from)
  : ::google::protobuf::Message(),
    _internal_metadata_(NULL) {
  SharedCtor();
  MergeFrom(from);
  // @@protoc_insertion_point(copy_constructor:google.protobuf.Option)
}

void Option::SharedCtor() {
    _is_default_instance_ = false;
  ::google::protobuf::internal::GetEmptyString();
  _cached_size_ = 0;
  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  value_ = NULL;
}

Option::~Option() {
  // @@protoc_insertion_point(destructor:google.protobuf.Option)
  SharedDtor();
}

void Option::SharedDtor() {
  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != default_instance_) {
    delete value_;
  }
}

void Option::SetCachedSize(int size) const {
  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const ::google::protobuf::Descriptor* Option::descriptor() {
  protobuf_AssignDescriptorsOnce();
  return Option_descriptor_;
}

const Option& Option::default_instance() {
  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto();
  return *default_instance_;
}

Option* Option::default_instance_ = NULL;

Option* Option::New(::google::protobuf::Arena* arena) const {
  Option* n = new Option;
  if (arena != NULL) {
    arena->Own(n);
  }
  return n;
}

void Option::Clear() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
  value_ = NULL;
}

bool Option::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:google.protobuf.Option)
  for (;;) {
    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // optional string name = 1;
      case 1: {
        if (tag == 10) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_name()));
          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
            this->name().data(), this->name().length(),
            ::google::protobuf::internal::WireFormat::PARSE,
            "google.protobuf.Option.name");
        } else {
          goto handle_unusual;
        }
        if (input->ExpectTag(18)) goto parse_value;
        break;
      }

      // optional .google.protobuf.Any value = 2;
      case 2: {
        if (tag == 18) {
         parse_value:
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, mutable_value()));
        } else {
          goto handle_unusual;
        }
        if (input->ExpectAtEnd()) goto success;
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0 ||
            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:google.protobuf.Option)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:google.protobuf.Option)
  return false;
#undef DO_
}

void Option::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:google.protobuf.Option)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Option.name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      1, this->name(), output);
  }

  // optional .google.protobuf.Any value = 2;
  if (this->has_value()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, *this->value_, output);
  }

  // @@protoc_insertion_point(serialize_end:google.protobuf.Option)
}

::google::protobuf::uint8* Option::SerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
  // optional string name = 1;
  if (this->name().size() > 0) {
    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
      this->name().data(), this->name().length(),
      ::google::protobuf::internal::WireFormat::SERIALIZE,
      "google.protobuf.Option.name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        1, this->name(), target);
  }

  // optional .google.protobuf.Any value = 2;
  if (this->has_value()) {
    target = ::google::protobuf::internal::WireFormatLite::
      WriteMessageNoVirtualToArray(
        2, *this->value_, target);
  }

  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Option)
  return target;
}

int Option::ByteSize() const {
  int total_size = 0;

  // optional string name = 1;
  if (this->name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->name());
  }

  // optional .google.protobuf.Any value = 2;
  if (this->has_value()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
        *this->value_);
  }

  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
  _cached_size_ = total_size;
  GOOGLE_SAFE_CONCURRENT_WRITES_END();
  return total_size;
}

void Option::MergeFrom(const ::google::protobuf::Message& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  const Option* source = 
      ::google::protobuf::internal::DynamicCastToGenerated<const Option>(
          &from);
  if (source == NULL) {
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
    MergeFrom(*source);
  }
}

void Option::MergeFrom(const Option& from) {
  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
  if (from.name().size() > 0) {

    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
  }
  if (from.has_value()) {
    mutable_value()->::google::protobuf::Any::MergeFrom(from.value());
  }
}

void Option::CopyFrom(const ::google::protobuf::Message& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Option::CopyFrom(const Option& from) {
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Option::IsInitialized() const {

  return true;
}

void Option::Swap(Option* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Option::InternalSwap(Option* other) {
  name_.Swap(&other->name_);
  std::swap(value_, other->value_);
  _internal_metadata_.Swap(&other->_internal_metadata_);
  std::swap(_cached_size_, other->_cached_size_);
}

::google::protobuf::Metadata Option::GetMetadata() const {
  protobuf_AssignDescriptorsOnce();
  ::google::protobuf::Metadata metadata;
  metadata.descriptor = Option_descriptor_;
  metadata.reflection = Option_reflection_;
  return metadata;
}

#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Option

// optional string name = 1;
void Option::clear_name() {
  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 const ::std::string& Option::name() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
  return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Option::set_name(const ::std::string& value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
}
 void Option::set_name(const char* value) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
}
 void Option::set_name(const char* value, size_t size) {
  
  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
}
 ::std::string* Option::mutable_name() {
  
  // @@protoc_insertion_point(field_mutable:google.protobuf.Option.name)
  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 ::std::string* Option::release_name() {
  
  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
 void Option::set_allocated_name(::std::string* name) {
  if (name != NULL) {
    
  } else {
    
  }
  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.name)
}

// optional .google.protobuf.Any value = 2;
bool Option::has_value() const {
  return !_is_default_instance_ && value_ != NULL;
}
void Option::clear_value() {
  if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
  value_ = NULL;
}
 const ::google::protobuf::Any& Option::value() const {
  // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
  return value_ != NULL ? *value_ : *default_instance_->value_;
}
 ::google::protobuf::Any* Option::mutable_value() {
  
  if (value_ == NULL) {
    value_ = new ::google::protobuf::Any;
  }
  // @@protoc_insertion_point(field_mutable:google.protobuf.Option.value)
  return value_;
}
 ::google::protobuf::Any* Option::release_value() {
  
  ::google::protobuf::Any* temp = value_;
  value_ = NULL;
  return temp;
}
 void Option::set_allocated_value(::google::protobuf::Any* value) {
  delete value_;
  value_ = value;
  if (value) {
    
  } else {
    
  }
  // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
}

#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS

// @@protoc_insertion_point(namespace_scope)

}  // namespace protobuf
}  // namespace google

// @@protoc_insertion_point(global_scope)
