// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/protobuf/unittest_custom_options.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace Google.ProtocolBuffers.TestProtos {

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public static partial class UnittestCustomOptions {

    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FileOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.MessageOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FieldOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FieldOpt2);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.EnumOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.EnumValueOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ServiceOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.MethodOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.BoolOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Int32Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Int64Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Uint32Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Uint64Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sint32Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sint64Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fixed32Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fixed64Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sfixed32Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sfixed64Opt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FloatOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.DoubleOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.StringOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.BytesOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.EnumOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.MessageTypeOpt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Quux);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Corge);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Grault);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Garply);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt1);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt2);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt3);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt6);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fileopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Msgopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fieldopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Enumopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Enumvalopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Serviceopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Methodopt);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.ComplexOpt4);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.MessageSetExtension);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.Aggregate.Nested);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.NestedOptionType.NestedExtension);
    }
    #endregion
    #region Extensions
    public const int FileOpt1FieldNumber = 7736974;
    [global::System.CLSCompliant(false)]
    public static pb::GeneratedExtensionBase<ulong> FileOpt1;
    public const int MessageOpt1FieldNumber = 7739036;
    public static pb::GeneratedExtensionBase<int> MessageOpt1;
    public const int FieldOpt1FieldNumber = 7740936;
    [global::System.CLSCompliant(false)]
    public static pb::GeneratedExtensionBase<ulong> FieldOpt1;
    public const int FieldOpt2FieldNumber = 7753913;
    public static pb::GeneratedExtensionBase<int> FieldOpt2;
    public const int EnumOpt1FieldNumber = 7753576;
    public static pb::GeneratedExtensionBase<int> EnumOpt1;
    public const int EnumValueOpt1FieldNumber = 1560678;
    public static pb::GeneratedExtensionBase<int> EnumValueOpt1;
    public const int ServiceOpt1FieldNumber = 7887650;
    public static pb::GeneratedExtensionBase<long> ServiceOpt1;
    public const int MethodOpt1FieldNumber = 7890860;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.MethodOpt1> MethodOpt1;
    public const int BoolOptFieldNumber = 7706090;
    public static pb::GeneratedExtensionBase<bool> BoolOpt;
    public const int Int32OptFieldNumber = 7705709;
    public static pb::GeneratedExtensionBase<int> Int32Opt;
    public const int Int64OptFieldNumber = 7705542;
    public static pb::GeneratedExtensionBase<long> Int64Opt;
    public const int Uint32OptFieldNumber = 7704880;
    [global::System.CLSCompliant(false)]
    public static pb::GeneratedExtensionBase<uint> Uint32Opt;
    public const int Uint64OptFieldNumber = 7702367;
    [global::System.CLSCompliant(false)]
    public static pb::GeneratedExtensionBase<ulong> Uint64Opt;
    public const int Sint32OptFieldNumber = 7701568;
    public static pb::GeneratedExtensionBase<int> Sint32Opt;
    public const int Sint64OptFieldNumber = 7700863;
    public static pb::GeneratedExtensionBase<long> Sint64Opt;
    public const int Fixed32OptFieldNumber = 7700307;
    [global::System.CLSCompliant(false)]
    public static pb::GeneratedExtensionBase<uint> Fixed32Opt;
    public const int Fixed64OptFieldNumber = 7700194;
    [global::System.CLSCompliant(false)]
    public static pb::GeneratedExtensionBase<ulong> Fixed64Opt;
    public const int Sfixed32OptFieldNumber = 7698645;
    public static pb::GeneratedExtensionBase<int> Sfixed32Opt;
    public const int Sfixed64OptFieldNumber = 7685475;
    public static pb::GeneratedExtensionBase<long> Sfixed64Opt;
    public const int FloatOptFieldNumber = 7675390;
    public static pb::GeneratedExtensionBase<float> FloatOpt;
    public const int DoubleOptFieldNumber = 7673293;
    public static pb::GeneratedExtensionBase<double> DoubleOpt;
    public const int StringOptFieldNumber = 7673285;
    public static pb::GeneratedExtensionBase<string> StringOpt;
    public const int BytesOptFieldNumber = 7673238;
    public static pb::GeneratedExtensionBase<pb::ByteString> BytesOpt;
    public const int EnumOptFieldNumber = 7673233;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.Types.TestEnumType> EnumOpt;
    public const int MessageTypeOptFieldNumber = 7665967;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType> MessageTypeOpt;
    public const int QuuxFieldNumber = 7663707;
    public static pb::GeneratedExtensionBase<int> Quux;
    public const int CorgeFieldNumber = 7663442;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3> Corge;
    public const int GraultFieldNumber = 7650927;
    public static pb::GeneratedExtensionBase<int> Grault;
    public const int GarplyFieldNumber = 7649992;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1> Garply;
    public const int ComplexOpt1FieldNumber = 7646756;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1> ComplexOpt1;
    public const int ComplexOpt2FieldNumber = 7636949;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2> ComplexOpt2;
    public const int ComplexOpt3FieldNumber = 7636463;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3> ComplexOpt3;
    public const int ComplexOpt6FieldNumber = 7595468;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOpt6> ComplexOpt6;
    public const int FileoptFieldNumber = 15478479;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Fileopt;
    public const int MsgoptFieldNumber = 15480088;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Msgopt;
    public const int FieldoptFieldNumber = 15481374;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Fieldopt;
    public const int EnumoptFieldNumber = 15483218;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Enumopt;
    public const int EnumvaloptFieldNumber = 15486921;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Enumvalopt;
    public const int ServiceoptFieldNumber = 15497145;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Serviceopt;
    public const int MethodoptFieldNumber = 15512713;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Methodopt;
    #endregion

    #region Static variables
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestMessageWithCustomOptions__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions, global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions.Builder> internal__static_protobuf_unittest_TestMessageWithCustomOptions__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionFooRequest__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest.Builder> internal__static_protobuf_unittest_CustomOptionFooRequest__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionFooResponse__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.Builder> internal__static_protobuf_unittest_CustomOptionFooResponse__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionFooClientMessage__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage.Builder> internal__static_protobuf_unittest_CustomOptionFooClientMessage__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionFooServerMessage__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage.Builder> internal__static_protobuf_unittest_CustomOptionFooServerMessage__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_DummyMessageContainingEnum__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum, global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.Builder> internal__static_protobuf_unittest_DummyMessageContainingEnum__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType, global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType.Builder> internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionMinIntegerValues__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues, global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues.Builder> internal__static_protobuf_unittest_CustomOptionMinIntegerValues__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues, global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues.Builder> internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_CustomOptionOtherValues__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues, global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues.Builder> internal__static_protobuf_unittest_CustomOptionOtherValues__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_SettingRealsFromPositiveInts__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts, global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts.Builder> internal__static_protobuf_unittest_SettingRealsFromPositiveInts__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_SettingRealsFromNegativeInts__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts, global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts.Builder> internal__static_protobuf_unittest_SettingRealsFromNegativeInts__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ComplexOptionType1__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.Builder> internal__static_protobuf_unittest_ComplexOptionType1__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ComplexOptionType2__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Builder> internal__static_protobuf_unittest_ComplexOptionType2__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Builder> internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ComplexOptionType3__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Builder> internal__static_protobuf_unittest_ComplexOptionType3__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.Builder> internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ComplexOpt6__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOpt6, global::Google.ProtocolBuffers.TestProtos.ComplexOpt6.Builder> internal__static_protobuf_unittest_ComplexOpt6__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_VariousComplexOptions__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions, global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions.Builder> internal__static_protobuf_unittest_VariousComplexOptions__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_AggregateMessageSet__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet, global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.Builder> internal__static_protobuf_unittest_AggregateMessageSet__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_AggregateMessageSetElement__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement, global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.Builder> internal__static_protobuf_unittest_AggregateMessageSetElement__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_Aggregate__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.Aggregate, global::Google.ProtocolBuffers.TestProtos.Aggregate.Builder> internal__static_protobuf_unittest_Aggregate__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_AggregateMessage__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.AggregateMessage, global::Google.ProtocolBuffers.TestProtos.AggregateMessage.Builder> internal__static_protobuf_unittest_AggregateMessage__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_NestedOptionType__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.NestedOptionType, global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Builder> internal__static_protobuf_unittest_NestedOptionType__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_NestedOptionType_NestedMessage__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage, global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage.Builder> internal__static_protobuf_unittest_NestedOptionType_NestedMessage__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;

    static UnittestCustomOptions() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "Ci1nb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfY3VzdG9tX29wdGlvbnMucHJv", 
            "dG8SEXByb3RvYnVmX3VuaXR0ZXN0GiBnb29nbGUvcHJvdG9idWYvZGVzY3Jp", 
            "cHRvci5wcm90byKNAQocVGVzdE1lc3NhZ2VXaXRoQ3VzdG9tT3B0aW9ucxIe", 
            "CgZmaWVsZDEYASABKAlCDggBweDDHS3hdQoCAAAAIjsKBkFuRW51bRIPCgtB", 
            "TkVOVU1fVkFMMRABEhYKC0FORU5VTV9WQUwyEAIaBbCG+gV7GgjF9skd6/z/", 
            "/zoQCADg6cIdyP//////////ASIYChZDdXN0b21PcHRpb25Gb29SZXF1ZXN0", 
            "IhkKF0N1c3RvbU9wdGlvbkZvb1Jlc3BvbnNlIh4KHEN1c3RvbU9wdGlvbkZv", 
            "b0NsaWVudE1lc3NhZ2UiHgocQ3VzdG9tT3B0aW9uRm9vU2VydmVyTWVzc2Fn", 
            "ZSJtChpEdW1teU1lc3NhZ2VDb250YWluaW5nRW51bSJPCgxUZXN0RW51bVR5", 
            "cGUSGgoWVEVTVF9PUFRJT05fRU5VTV9UWVBFMRAWEiMKFlRFU1RfT1BUSU9O", 
            "X0VOVU1fVFlQRTIQ6f//////////ASIhCh9EdW1teU1lc3NhZ2VJbnZhbGlk", 
            "QXNPcHRpb25UeXBlIooBChxDdXN0b21PcHRpb25NaW5JbnRlZ2VyVmFsdWVz", 
            "OmrQ3rIdAOjGsh2AgICA+P////8BsLyyHYCAgICAgICAgAGAk7IdAPj1sB0A", 
            "gMSwHf////8P+JewHf///////////wGd9a8dAAAAAJHurx0AAAAAAAAAAK2N", 
            "rx0AAACAmdaoHQAAAAAAAACAIpEBChxDdXN0b21PcHRpb25NYXhJbnRlZ2Vy", 
            "VmFsdWVzOnHQ3rIdAejGsh3/////B7C8sh3//////////3+Ak7Id/////w/4", 
            "9bAd////////////AYDEsB3+////D/iXsB3+//////////8BnfWvHf////+R", 
            "7q8d//////////+tja8d////f5nWqB3/////////fyJuChdDdXN0b21PcHRp", 
            "b25PdGhlclZhbHVlczpT6MayHZz//////////wH136Md54dFQencoh37WYxC", 
            "ysDzP6rcoh0OSGVsbG8sICJXb3JsZCKy2aIdC0hlbGxvAFdvcmxkiNmiHen/", 
            "/////////wEiNAocU2V0dGluZ1JlYWxzRnJvbVBvc2l0aXZlSW50czoU9d+j", 
            "HQAAQEHp3KIdAAAAAABAY0AiNAocU2V0dGluZ1JlYWxzRnJvbU5lZ2F0aXZl", 
            "SW50czoU9d+jHQAAQMHp3KIdAAAAAABAY8AiVQoSQ29tcGxleE9wdGlvblR5", 
            "cGUxEgsKA2ZvbxgBIAEoBRIMCgRmb28yGAIgASgFEgwKBGZvbzMYAyABKAUS", 
            "DAoEZm9vNBgEIAMoBSoICGQQgICAgAIiiwMKEkNvbXBsZXhPcHRpb25UeXBl", 
            "MhIyCgNiYXIYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0", 
            "aW9uVHlwZTESCwoDYmF6GAIgASgFEkYKBGZyZWQYAyABKAsyOC5wcm90b2J1", 
            "Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTIuQ29tcGxleE9wdGlvblR5", 
            "cGU0EkgKBmJhcm5leRgEIAMoCzI4LnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBs", 
            "ZXhPcHRpb25UeXBlMi5Db21wbGV4T3B0aW9uVHlwZTQalwEKEkNvbXBsZXhP", 
            "cHRpb25UeXBlNBINCgV3YWxkbxgBIAEoBTJyCgxjb21wbGV4X29wdDQSHy5n", 
            "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYivXRAyABKAsyOC5wcm90", 
            "b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTIuQ29tcGxleE9wdGlv", 
            "blR5cGU0KggIZBCAgICAAiKcAQoSQ29tcGxleE9wdGlvblR5cGUzEgsKA3F1", 
            "eBgBIAEoBRJUChJjb21wbGV4b3B0aW9udHlwZTUYAiABKAoyOC5wcm90b2J1", 
            "Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTMuQ29tcGxleE9wdGlvblR5", 
            "cGU1GiMKEkNvbXBsZXhPcHRpb25UeXBlNRINCgVwbHVnaBgDIAEoBSIfCgtD", 
            "b21wbGV4T3B0NhIQCgV4eXp6eRjfv88DIAEoBSLxAQoVVmFyaW91c0NvbXBs", 
            "ZXhPcHRpb25zOtcBouKVHQIIKqLilR0G2IWeHcQCouKVHQiS9Z0dAwjsBqLi", 
            "lR0CIGOi4pUdAiBYqv2QHQMQ2weq/ZAdBvjmlx2OBar9kB0FCgMI5wWq/ZAd", 
            "CAoG2IWeHc8Pqv2QHQoKCJL1nR0DCNgPqv2QHQjCrJcdAwjlBar9kB0LwqyX", 
            "HQbYhZ4dzg+q/ZAdDcKslx0IkvWdHQMIyRDSqI8dAwizD6r9kB0FGgMIwQKq", 
            "/ZAdBCICCGWq/ZAdBSIDCNQB+t6QHQIICfrekB0EExgWFOPc/Bz4/fscGOTc", 
            "/BwiIwoTQWdncmVnYXRlTWVzc2FnZVNldCoICAQQ/////wc6AggBIqABChpB", 
            "Z2dyZWdhdGVNZXNzYWdlU2V0RWxlbWVudBIJCgFzGAEgASgJMncKFW1lc3Nh", 
            "Z2Vfc2V0X2V4dGVuc2lvbhImLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0", 
            "ZU1lc3NhZ2VTZXQY9uuuByABKAsyLS5wcm90b2J1Zl91bml0dGVzdC5BZ2dy", 
            "ZWdhdGVNZXNzYWdlU2V0RWxlbWVudCL9AQoJQWdncmVnYXRlEgkKAWkYASAB", 
            "KAUSCQoBcxgCIAEoCRIpCgNzdWIYAyABKAsyHC5wcm90b2J1Zl91bml0dGVz", 
            "dC5BZ2dyZWdhdGUSKgoEZmlsZRgEIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5G", 
            "aWxlT3B0aW9ucxI0CgRtc2V0GAUgASgLMiYucHJvdG9idWZfdW5pdHRlc3Qu", 
            "QWdncmVnYXRlTWVzc2FnZVNldDJNCgZuZXN0ZWQSHC5nb29nbGUucHJvdG9i", 
            "dWYuRmlsZU9wdGlvbnMYp9GwByABKAsyHC5wcm90b2J1Zl91bml0dGVzdC5B", 
            "Z2dyZWdhdGUiWQoQQWdncmVnYXRlTWVzc2FnZRIpCglmaWVsZG5hbWUYASAB", 
            "KAVCFvKhhzsREg9GaWVsZEFubm90YXRpb246GsLRhjsVCGUSEU1lc3NhZ2VB", 
            "bm5vdGF0aW9uIskBChBOZXN0ZWRPcHRpb25UeXBlGjsKDU5lc3RlZE1lc3Nh", 
            "Z2USIgoMbmVzdGVkX2ZpZWxkGAEgASgFQgzB4MMd6gMAAAAAAAA6BuDpwh3p", 
            "ByI1CgpOZXN0ZWRFbnVtEh0KEU5FU1RFRF9FTlVNX1ZBTFVFEAEaBrCG+gXs", 
            "BxoIxfbJHesDAAAyQQoQbmVzdGVkX2V4dGVuc2lvbhIcLmdvb2dsZS5wcm90", 
            "b2J1Zi5GaWxlT3B0aW9ucxj9+OIDIAEoBUIGyIvKHe0HKjYKCk1ldGhvZE9w", 
            "dDESEwoPTUVUSE9ET1BUMV9WQUwxEAESEwoPTUVUSE9ET1BUMV9WQUwyEAIq", 
            "TQoNQWdncmVnYXRlRW51bRIlCgVWQUxVRRABGhrK/Ik7FRITRW51bVZhbHVl", 
            "QW5ub3RhdGlvbhoVkpWIOxASDkVudW1Bbm5vdGF0aW9uMo4BChxUZXN0U2Vy", 
            "dmljZVdpdGhDdXN0b21PcHRpb25zEmMKA0ZvbxIpLnByb3RvYnVmX3VuaXR0", 
            "ZXN0LkN1c3RvbU9wdGlvbkZvb1JlcXVlc3QaKi5wcm90b2J1Zl91bml0dGVz", 
            "dC5DdXN0b21PcHRpb25Gb29SZXNwb25zZSIF4PqMHgIaCZCyix7T24DLSTKZ", 
            "AQoQQWdncmVnYXRlU2VydmljZRJrCgZNZXRob2QSIy5wcm90b2J1Zl91bml0", 
            "dGVzdC5BZ2dyZWdhdGVNZXNzYWdlGiMucHJvdG9idWZfdW5pdHRlc3QuQWdn", 
            "cmVnYXRlTWVzc2FnZSIXysiWOxISEE1ldGhvZEFubm90YXRpb24aGMr7jjsT", 
            "EhFTZXJ2aWNlQW5ub3RhdGlvbjoyCglmaWxlX29wdDESHC5nb29nbGUucHJv", 
            "dG9idWYuRmlsZU9wdGlvbnMYjp3YAyABKAQ6OAoMbWVzc2FnZV9vcHQxEh8u", 
            "Z29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGJyt2AMgASgFOjQKCmZp", 
            "ZWxkX29wdDESHS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGIi82AMg", 
            "ASgGOjgKCmZpZWxkX29wdDISHS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRp", 
            "b25zGLmh2QMgASgFOgI0MjoyCgllbnVtX29wdDESHC5nb29nbGUucHJvdG9i", 
            "dWYuRW51bU9wdGlvbnMY6J7ZAyABKA86PAoPZW51bV92YWx1ZV9vcHQxEiEu", 
            "Z29vZ2xlLnByb3RvYnVmLkVudW1WYWx1ZU9wdGlvbnMY5qBfIAEoBTo4Cgxz", 
            "ZXJ2aWNlX29wdDESHy5nb29nbGUucHJvdG9idWYuU2VydmljZU9wdGlvbnMY", 
            "orbhAyABKBI6VQoLbWV0aG9kX29wdDESHi5nb29nbGUucHJvdG9idWYuTWV0", 
            "aG9kT3B0aW9ucxisz+EDIAEoDjIdLnByb3RvYnVmX3VuaXR0ZXN0Lk1ldGhv", 
            "ZE9wdDE6NAoIYm9vbF9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9w", 
            "dGlvbnMY6qvWAyABKAg6NQoJaW50MzJfb3B0Eh8uZ29vZ2xlLnByb3RvYnVm", 
            "Lk1lc3NhZ2VPcHRpb25zGO2o1gMgASgFOjUKCWludDY0X29wdBIfLmdvb2ds", 
            "ZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxjGp9YDIAEoAzo2Cgp1aW50MzJf", 
            "b3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGLCi1gMgASgN", 
            "OjYKCnVpbnQ2NF9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlv", 
            "bnMY347WAyABKAQ6NgoKc2ludDMyX29wdBIfLmdvb2dsZS5wcm90b2J1Zi5N", 
            "ZXNzYWdlT3B0aW9ucxjAiNYDIAEoETo2CgpzaW50NjRfb3B0Eh8uZ29vZ2xl", 
            "LnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGP+C1gMgASgSOjcKC2ZpeGVkMzJf", 
            "b3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGNP+1QMgASgH", 
            "OjcKC2ZpeGVkNjRfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRp", 
            "b25zGOL91QMgASgGOjgKDHNmaXhlZDMyX29wdBIfLmdvb2dsZS5wcm90b2J1", 
            "Zi5NZXNzYWdlT3B0aW9ucxjV8dUDIAEoDzo4CgxzZml4ZWQ2NF9vcHQSHy5n", 
            "b29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY44rVAyABKBA6NQoJZmxv", 
            "YXRfb3B0Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGP671AMg", 
            "ASgCOjYKCmRvdWJsZV9vcHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9w", 
            "dGlvbnMYzavUAyABKAE6NgoKc3RyaW5nX29wdBIfLmdvb2dsZS5wcm90b2J1", 
            "Zi5NZXNzYWdlT3B0aW9ucxjFq9QDIAEoCTo1CglieXRlc19vcHQSHy5nb29n", 
            "bGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYlqvUAyABKAw6cAoIZW51bV9v", 
            "cHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYkavUAyABKA4y", 
            "Oi5wcm90b2J1Zl91bml0dGVzdC5EdW1teU1lc3NhZ2VDb250YWluaW5nRW51", 
            "bS5UZXN0RW51bVR5cGU6cAoQbWVzc2FnZV90eXBlX29wdBIfLmdvb2dsZS5w", 
            "cm90b2J1Zi5NZXNzYWdlT3B0aW9ucxiv8tMDIAEoCzIyLnByb3RvYnVmX3Vu", 
            "aXR0ZXN0LkR1bW15TWVzc2FnZUludmFsaWRBc09wdGlvblR5cGU6NgoEcXV1", 
            "eBIlLnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRpb25UeXBlMRjb4NMD", 
            "IAEoBTpeCgVjb3JnZRIlLnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRp", 
            "b25UeXBlMRjS3tMDIAEoCzIlLnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhP", 
            "cHRpb25UeXBlMzo4CgZncmF1bHQSJS5wcm90b2J1Zl91bml0dGVzdC5Db21w", 
            "bGV4T3B0aW9uVHlwZTIY7/zSAyABKAU6XwoGZ2FycGx5EiUucHJvdG9idWZf", 
            "dW5pdHRlc3QuQ29tcGxleE9wdGlvblR5cGUyGMj10gMgASgLMiUucHJvdG9i", 
            "dWZfdW5pdHRlc3QuQ29tcGxleE9wdGlvblR5cGUxOl8KDGNvbXBsZXhfb3B0", 
            "MRIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxik3NIDIAEoCzIl", 
            "LnByb3RvYnVmX3VuaXR0ZXN0LkNvbXBsZXhPcHRpb25UeXBlMTpfCgxjb21w", 
            "bGV4X29wdDISHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMY1Y/S", 
            "AyABKAsyJS5wcm90b2J1Zl91bml0dGVzdC5Db21wbGV4T3B0aW9uVHlwZTI6", 
            "XwoMY29tcGxleF9vcHQzEh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRp", 
            "b25zGO+L0gMgASgLMiUucHJvdG9idWZfdW5pdHRlc3QuQ29tcGxleE9wdGlv", 
            "blR5cGUzOlcKC2NvbXBsZXhvcHQ2Eh8uZ29vZ2xlLnByb3RvYnVmLk1lc3Nh", 
            "Z2VPcHRpb25zGMzLzwMgASgKMh4ucHJvdG9idWZfdW5pdHRlc3QuQ29tcGxl", 
            "eE9wdDY6TgoHZmlsZW9wdBIcLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9u", 
            "cxjP3bAHIAEoCzIcLnByb3RvYnVmX3VuaXR0ZXN0LkFnZ3JlZ2F0ZTpQCgZt", 
            "c2dvcHQSHy5nb29nbGUucHJvdG9idWYuTWVzc2FnZU9wdGlvbnMYmOqwByAB", 
            "KAsyHC5wcm90b2J1Zl91bml0dGVzdC5BZ2dyZWdhdGU6UAoIZmllbGRvcHQS", 
            "HS5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zGJ70sAcgASgLMhwucHJv", 
            "dG9idWZfdW5pdHRlc3QuQWdncmVnYXRlOk4KB2VudW1vcHQSHC5nb29nbGUu", 
            "cHJvdG9idWYuRW51bU9wdGlvbnMY0oKxByABKAsyHC5wcm90b2J1Zl91bml0", 
            "dGVzdC5BZ2dyZWdhdGU6VgoKZW51bXZhbG9wdBIhLmdvb2dsZS5wcm90b2J1", 
            "Zi5FbnVtVmFsdWVPcHRpb25zGMmfsQcgASgLMhwucHJvdG9idWZfdW5pdHRl", 
            "c3QuQWdncmVnYXRlOlQKCnNlcnZpY2VvcHQSHy5nb29nbGUucHJvdG9idWYu", 
            "U2VydmljZU9wdGlvbnMYue+xByABKAsyHC5wcm90b2J1Zl91bml0dGVzdC5B", 
            "Z2dyZWdhdGU6UgoJbWV0aG9kb3B0Eh4uZ29vZ2xlLnByb3RvYnVmLk1ldGhv", 
            "ZE9wdGlvbnMYiemyByABKAsyHC5wcm90b2J1Zl91bml0dGVzdC5BZ2dyZWdh", 
            "dGVCqwGAAQGIAQGQAQGqAiFHb29nbGUuUHJvdG9jb2xCdWZmZXJzLlRlc3RQ", 
            "cm90b3Pw6MEd6q3A5ST67IU7cAhkEg5GaWxlQW5ub3RhdGlvbhoWEhROZXN0", 
            "ZWRGaWxlQW5ub3RhdGlvbiIe+uyFOxkSF0ZpbGVFeHRlbnNpb25Bbm5vdGF0", 
          "aW9uKiQLEPbrrgcaGwoZRW1iZWRkZWRNZXNzYWdlU2V0RWxlbWVudAw="));
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_protobuf_unittest_TestMessageWithCustomOptions__Descriptor = Descriptor.MessageTypes[0];
        internal__static_protobuf_unittest_TestMessageWithCustomOptions__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions, global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions.Builder>(internal__static_protobuf_unittest_TestMessageWithCustomOptions__Descriptor,
                new string[] { "Field1", });
        internal__static_protobuf_unittest_CustomOptionFooRequest__Descriptor = Descriptor.MessageTypes[1];
        internal__static_protobuf_unittest_CustomOptionFooRequest__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest.Builder>(internal__static_protobuf_unittest_CustomOptionFooRequest__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_CustomOptionFooResponse__Descriptor = Descriptor.MessageTypes[2];
        internal__static_protobuf_unittest_CustomOptionFooResponse__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.Builder>(internal__static_protobuf_unittest_CustomOptionFooResponse__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_CustomOptionFooClientMessage__Descriptor = Descriptor.MessageTypes[3];
        internal__static_protobuf_unittest_CustomOptionFooClientMessage__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage.Builder>(internal__static_protobuf_unittest_CustomOptionFooClientMessage__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_CustomOptionFooServerMessage__Descriptor = Descriptor.MessageTypes[4];
        internal__static_protobuf_unittest_CustomOptionFooServerMessage__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage, global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage.Builder>(internal__static_protobuf_unittest_CustomOptionFooServerMessage__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_DummyMessageContainingEnum__Descriptor = Descriptor.MessageTypes[5];
        internal__static_protobuf_unittest_DummyMessageContainingEnum__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum, global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.Builder>(internal__static_protobuf_unittest_DummyMessageContainingEnum__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__Descriptor = Descriptor.MessageTypes[6];
        internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType, global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType.Builder>(internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_CustomOptionMinIntegerValues__Descriptor = Descriptor.MessageTypes[7];
        internal__static_protobuf_unittest_CustomOptionMinIntegerValues__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues, global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues.Builder>(internal__static_protobuf_unittest_CustomOptionMinIntegerValues__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__Descriptor = Descriptor.MessageTypes[8];
        internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues, global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues.Builder>(internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_CustomOptionOtherValues__Descriptor = Descriptor.MessageTypes[9];
        internal__static_protobuf_unittest_CustomOptionOtherValues__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues, global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues.Builder>(internal__static_protobuf_unittest_CustomOptionOtherValues__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_SettingRealsFromPositiveInts__Descriptor = Descriptor.MessageTypes[10];
        internal__static_protobuf_unittest_SettingRealsFromPositiveInts__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts, global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts.Builder>(internal__static_protobuf_unittest_SettingRealsFromPositiveInts__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_SettingRealsFromNegativeInts__Descriptor = Descriptor.MessageTypes[11];
        internal__static_protobuf_unittest_SettingRealsFromNegativeInts__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts, global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts.Builder>(internal__static_protobuf_unittest_SettingRealsFromNegativeInts__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_ComplexOptionType1__Descriptor = Descriptor.MessageTypes[12];
        internal__static_protobuf_unittest_ComplexOptionType1__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.Builder>(internal__static_protobuf_unittest_ComplexOptionType1__Descriptor,
                new string[] { "Foo", "Foo2", "Foo3", "Foo4", });
        internal__static_protobuf_unittest_ComplexOptionType2__Descriptor = Descriptor.MessageTypes[13];
        internal__static_protobuf_unittest_ComplexOptionType2__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Builder>(internal__static_protobuf_unittest_ComplexOptionType2__Descriptor,
                new string[] { "Bar", "Baz", "Fred", "Barney", });
        internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__Descriptor = internal__static_protobuf_unittest_ComplexOptionType2__Descriptor.NestedTypes[0];
        internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Builder>(internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__Descriptor,
                new string[] { "Waldo", });
        global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.ComplexOpt4 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Descriptor.Extensions[0]);
        internal__static_protobuf_unittest_ComplexOptionType3__Descriptor = Descriptor.MessageTypes[14];
        internal__static_protobuf_unittest_ComplexOptionType3__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Builder>(internal__static_protobuf_unittest_ComplexOptionType3__Descriptor,
                new string[] { "Qux", "ComplexOptionType5", });
        internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__Descriptor = internal__static_protobuf_unittest_ComplexOptionType3__Descriptor.NestedTypes[0];
        internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.Builder>(internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__Descriptor,
                new string[] { "Plugh", });
        internal__static_protobuf_unittest_ComplexOpt6__Descriptor = Descriptor.MessageTypes[15];
        internal__static_protobuf_unittest_ComplexOpt6__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.ComplexOpt6, global::Google.ProtocolBuffers.TestProtos.ComplexOpt6.Builder>(internal__static_protobuf_unittest_ComplexOpt6__Descriptor,
                new string[] { "Xyzzy", });
        internal__static_protobuf_unittest_VariousComplexOptions__Descriptor = Descriptor.MessageTypes[16];
        internal__static_protobuf_unittest_VariousComplexOptions__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions, global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions.Builder>(internal__static_protobuf_unittest_VariousComplexOptions__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_AggregateMessageSet__Descriptor = Descriptor.MessageTypes[17];
        internal__static_protobuf_unittest_AggregateMessageSet__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet, global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.Builder>(internal__static_protobuf_unittest_AggregateMessageSet__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_AggregateMessageSetElement__Descriptor = Descriptor.MessageTypes[18];
        internal__static_protobuf_unittest_AggregateMessageSetElement__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement, global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.Builder>(internal__static_protobuf_unittest_AggregateMessageSetElement__Descriptor,
                new string[] { "S", });
        global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.MessageSetExtension = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.Descriptor.Extensions[0]);
        internal__static_protobuf_unittest_Aggregate__Descriptor = Descriptor.MessageTypes[19];
        internal__static_protobuf_unittest_Aggregate__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.Aggregate, global::Google.ProtocolBuffers.TestProtos.Aggregate.Builder>(internal__static_protobuf_unittest_Aggregate__Descriptor,
                new string[] { "I", "S", "Sub", "File", "Mset", });
        global::Google.ProtocolBuffers.TestProtos.Aggregate.Nested = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.Aggregate.Descriptor.Extensions[0]);
        internal__static_protobuf_unittest_AggregateMessage__Descriptor = Descriptor.MessageTypes[20];
        internal__static_protobuf_unittest_AggregateMessage__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.AggregateMessage, global::Google.ProtocolBuffers.TestProtos.AggregateMessage.Builder>(internal__static_protobuf_unittest_AggregateMessage__Descriptor,
                new string[] { "Fieldname", });
        internal__static_protobuf_unittest_NestedOptionType__Descriptor = Descriptor.MessageTypes[21];
        internal__static_protobuf_unittest_NestedOptionType__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.NestedOptionType, global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Builder>(internal__static_protobuf_unittest_NestedOptionType__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_NestedOptionType_NestedMessage__Descriptor = internal__static_protobuf_unittest_NestedOptionType__Descriptor.NestedTypes[0];
        internal__static_protobuf_unittest_NestedOptionType_NestedMessage__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage, global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage.Builder>(internal__static_protobuf_unittest_NestedOptionType_NestedMessage__Descriptor,
                new string[] { "NestedField", });
        global::Google.ProtocolBuffers.TestProtos.NestedOptionType.NestedExtension = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Descriptor.Extensions[0]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FileOpt1 = pb::GeneratedSingleExtension<ulong>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[0]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.MessageOpt1 = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[1]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FieldOpt1 = pb::GeneratedSingleExtension<ulong>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[2]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FieldOpt2 = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[3]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.EnumOpt1 = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[4]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.EnumValueOpt1 = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[5]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ServiceOpt1 = pb::GeneratedSingleExtension<long>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[6]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.MethodOpt1 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.MethodOpt1>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[7]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.BoolOpt = pb::GeneratedSingleExtension<bool>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[8]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Int32Opt = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[9]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Int64Opt = pb::GeneratedSingleExtension<long>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[10]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Uint32Opt = pb::GeneratedSingleExtension<uint>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[11]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Uint64Opt = pb::GeneratedSingleExtension<ulong>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[12]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sint32Opt = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[13]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sint64Opt = pb::GeneratedSingleExtension<long>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[14]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fixed32Opt = pb::GeneratedSingleExtension<uint>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[15]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fixed64Opt = pb::GeneratedSingleExtension<ulong>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[16]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sfixed32Opt = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[17]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Sfixed64Opt = pb::GeneratedSingleExtension<long>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[18]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.FloatOpt = pb::GeneratedSingleExtension<float>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[19]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.DoubleOpt = pb::GeneratedSingleExtension<double>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[20]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.StringOpt = pb::GeneratedSingleExtension<string>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[21]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.BytesOpt = pb::GeneratedSingleExtension<pb::ByteString>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[22]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.EnumOpt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.Types.TestEnumType>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[23]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.MessageTypeOpt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[24]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Quux = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[25]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Corge = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[26]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Grault = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[27]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Garply = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[28]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt1 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[29]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt2 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[30]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt3 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[31]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.ComplexOpt6 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.ComplexOpt6>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[32]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fileopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[33]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Msgopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[34]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Fieldopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[35]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Enumopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[36]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Enumvalopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[37]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Serviceopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[38]);
        global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Methodopt = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.Aggregate>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor.Extensions[39]);
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor, 
          }, assigner);
    }
    #endregion

  }
  #region Enums
  public enum MethodOpt1 {
    METHODOPT1_VAL1 = 1,
    METHODOPT1_VAL2 = 2,
  }

  public enum AggregateEnum {
    VALUE = 1,
  }

  #endregion

  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestMessageWithCustomOptions : pb::GeneratedMessage<TestMessageWithCustomOptions, TestMessageWithCustomOptions.Builder> {
    private TestMessageWithCustomOptions() { }
    private static readonly TestMessageWithCustomOptions defaultInstance = new TestMessageWithCustomOptions().MakeReadOnly();
    private static readonly string[] _testMessageWithCustomOptionsFieldNames = new string[] { "field1" };
    private static readonly uint[] _testMessageWithCustomOptionsFieldTags = new uint[] { 10 };
    public static TestMessageWithCustomOptions DefaultInstance {
      get { return defaultInstance; }
    }

    public override TestMessageWithCustomOptions DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override TestMessageWithCustomOptions ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_TestMessageWithCustomOptions__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<TestMessageWithCustomOptions, TestMessageWithCustomOptions.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_TestMessageWithCustomOptions__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      public enum AnEnum {
        ANENUM_VAL1 = 1,
        ANENUM_VAL2 = 2,
      }

    }
    #endregion

    public const int Field1FieldNumber = 1;
    private bool hasField1;
    private string field1_ = "";
    public bool HasField1 {
      get { return hasField1; }
    }
    public string Field1 {
      get { return field1_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _testMessageWithCustomOptionsFieldNames;
      if (hasField1) {
        output.WriteString(1, field_names[0], Field1);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasField1) {
        size += pb::CodedOutputStream.ComputeStringSize(1, Field1);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static TestMessageWithCustomOptions ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestMessageWithCustomOptions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestMessageWithCustomOptions MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(TestMessageWithCustomOptions prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<TestMessageWithCustomOptions, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(TestMessageWithCustomOptions cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private TestMessageWithCustomOptions result;

      private TestMessageWithCustomOptions PrepareBuilder() {
        if (resultIsReadOnly) {
          TestMessageWithCustomOptions original = result;
          result = new TestMessageWithCustomOptions();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override TestMessageWithCustomOptions MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions.Descriptor; }
      }

      public override TestMessageWithCustomOptions DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions.DefaultInstance; }
      }

      public override TestMessageWithCustomOptions BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is TestMessageWithCustomOptions) {
          return MergeFrom((TestMessageWithCustomOptions) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(TestMessageWithCustomOptions other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestMessageWithCustomOptions.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasField1) {
          Field1 = other.Field1;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_testMessageWithCustomOptionsFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _testMessageWithCustomOptionsFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 10: {
              result.hasField1 = input.ReadString(ref result.field1_);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasField1 {
        get { return result.hasField1; }
      }
      public string Field1 {
        get { return result.Field1; }
        set { SetField1(value); }
      }
      public Builder SetField1(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasField1 = true;
        result.field1_ = value;
        return this;
      }
      public Builder ClearField1() {
        PrepareBuilder();
        result.hasField1 = false;
        result.field1_ = "";
        return this;
      }
    }
    static TestMessageWithCustomOptions() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionFooRequest : pb::GeneratedMessage<CustomOptionFooRequest, CustomOptionFooRequest.Builder> {
    private CustomOptionFooRequest() { }
    private static readonly CustomOptionFooRequest defaultInstance = new CustomOptionFooRequest().MakeReadOnly();
    private static readonly string[] _customOptionFooRequestFieldNames = new string[] {  };
    private static readonly uint[] _customOptionFooRequestFieldTags = new uint[] {  };
    public static CustomOptionFooRequest DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionFooRequest DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionFooRequest ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooRequest__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionFooRequest, CustomOptionFooRequest.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooRequest__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionFooRequestFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionFooRequest ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionFooRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionFooRequest MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionFooRequest prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionFooRequest, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionFooRequest cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionFooRequest result;

      private CustomOptionFooRequest PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionFooRequest original = result;
          result = new CustomOptionFooRequest();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionFooRequest MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest.Descriptor; }
      }

      public override CustomOptionFooRequest DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest.DefaultInstance; }
      }

      public override CustomOptionFooRequest BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionFooRequest) {
          return MergeFrom((CustomOptionFooRequest) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionFooRequest other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionFooRequest.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionFooRequestFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionFooRequestFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionFooRequest() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionFooResponse : pb::GeneratedMessage<CustomOptionFooResponse, CustomOptionFooResponse.Builder> {
    private CustomOptionFooResponse() { }
    private static readonly CustomOptionFooResponse defaultInstance = new CustomOptionFooResponse().MakeReadOnly();
    private static readonly string[] _customOptionFooResponseFieldNames = new string[] {  };
    private static readonly uint[] _customOptionFooResponseFieldTags = new uint[] {  };
    public static CustomOptionFooResponse DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionFooResponse DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionFooResponse ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooResponse__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionFooResponse, CustomOptionFooResponse.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooResponse__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionFooResponseFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionFooResponse ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionFooResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionFooResponse MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionFooResponse prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionFooResponse, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionFooResponse cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionFooResponse result;

      private CustomOptionFooResponse PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionFooResponse original = result;
          result = new CustomOptionFooResponse();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionFooResponse MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.Descriptor; }
      }

      public override CustomOptionFooResponse DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.DefaultInstance; }
      }

      public override CustomOptionFooResponse BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionFooResponse) {
          return MergeFrom((CustomOptionFooResponse) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionFooResponse other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionFooResponse.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionFooResponseFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionFooResponseFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionFooResponse() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionFooClientMessage : pb::GeneratedMessage<CustomOptionFooClientMessage, CustomOptionFooClientMessage.Builder> {
    private CustomOptionFooClientMessage() { }
    private static readonly CustomOptionFooClientMessage defaultInstance = new CustomOptionFooClientMessage().MakeReadOnly();
    private static readonly string[] _customOptionFooClientMessageFieldNames = new string[] {  };
    private static readonly uint[] _customOptionFooClientMessageFieldTags = new uint[] {  };
    public static CustomOptionFooClientMessage DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionFooClientMessage DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionFooClientMessage ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooClientMessage__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionFooClientMessage, CustomOptionFooClientMessage.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooClientMessage__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionFooClientMessageFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionFooClientMessage ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooClientMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionFooClientMessage MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionFooClientMessage prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionFooClientMessage, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionFooClientMessage cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionFooClientMessage result;

      private CustomOptionFooClientMessage PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionFooClientMessage original = result;
          result = new CustomOptionFooClientMessage();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionFooClientMessage MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage.Descriptor; }
      }

      public override CustomOptionFooClientMessage DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage.DefaultInstance; }
      }

      public override CustomOptionFooClientMessage BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionFooClientMessage) {
          return MergeFrom((CustomOptionFooClientMessage) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionFooClientMessage other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionFooClientMessage.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionFooClientMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionFooClientMessageFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionFooClientMessage() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionFooServerMessage : pb::GeneratedMessage<CustomOptionFooServerMessage, CustomOptionFooServerMessage.Builder> {
    private CustomOptionFooServerMessage() { }
    private static readonly CustomOptionFooServerMessage defaultInstance = new CustomOptionFooServerMessage().MakeReadOnly();
    private static readonly string[] _customOptionFooServerMessageFieldNames = new string[] {  };
    private static readonly uint[] _customOptionFooServerMessageFieldTags = new uint[] {  };
    public static CustomOptionFooServerMessage DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionFooServerMessage DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionFooServerMessage ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooServerMessage__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionFooServerMessage, CustomOptionFooServerMessage.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionFooServerMessage__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionFooServerMessageFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionFooServerMessage ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionFooServerMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionFooServerMessage MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionFooServerMessage prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionFooServerMessage, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionFooServerMessage cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionFooServerMessage result;

      private CustomOptionFooServerMessage PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionFooServerMessage original = result;
          result = new CustomOptionFooServerMessage();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionFooServerMessage MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage.Descriptor; }
      }

      public override CustomOptionFooServerMessage DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage.DefaultInstance; }
      }

      public override CustomOptionFooServerMessage BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionFooServerMessage) {
          return MergeFrom((CustomOptionFooServerMessage) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionFooServerMessage other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionFooServerMessage.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionFooServerMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionFooServerMessageFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionFooServerMessage() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class DummyMessageContainingEnum : pb::GeneratedMessage<DummyMessageContainingEnum, DummyMessageContainingEnum.Builder> {
    private DummyMessageContainingEnum() { }
    private static readonly DummyMessageContainingEnum defaultInstance = new DummyMessageContainingEnum().MakeReadOnly();
    private static readonly string[] _dummyMessageContainingEnumFieldNames = new string[] {  };
    private static readonly uint[] _dummyMessageContainingEnumFieldTags = new uint[] {  };
    public static DummyMessageContainingEnum DefaultInstance {
      get { return defaultInstance; }
    }

    public override DummyMessageContainingEnum DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override DummyMessageContainingEnum ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_DummyMessageContainingEnum__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<DummyMessageContainingEnum, DummyMessageContainingEnum.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_DummyMessageContainingEnum__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      public enum TestEnumType {
        TEST_OPTION_ENUM_TYPE1 = 22,
        TEST_OPTION_ENUM_TYPE2 = -23,
      }

    }
    #endregion

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _dummyMessageContainingEnumFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static DummyMessageContainingEnum ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DummyMessageContainingEnum ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private DummyMessageContainingEnum MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(DummyMessageContainingEnum prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<DummyMessageContainingEnum, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(DummyMessageContainingEnum cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private DummyMessageContainingEnum result;

      private DummyMessageContainingEnum PrepareBuilder() {
        if (resultIsReadOnly) {
          DummyMessageContainingEnum original = result;
          result = new DummyMessageContainingEnum();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override DummyMessageContainingEnum MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.Descriptor; }
      }

      public override DummyMessageContainingEnum DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.DefaultInstance; }
      }

      public override DummyMessageContainingEnum BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is DummyMessageContainingEnum) {
          return MergeFrom((DummyMessageContainingEnum) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(DummyMessageContainingEnum other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.DummyMessageContainingEnum.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_dummyMessageContainingEnumFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _dummyMessageContainingEnumFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static DummyMessageContainingEnum() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class DummyMessageInvalidAsOptionType : pb::GeneratedMessage<DummyMessageInvalidAsOptionType, DummyMessageInvalidAsOptionType.Builder> {
    private DummyMessageInvalidAsOptionType() { }
    private static readonly DummyMessageInvalidAsOptionType defaultInstance = new DummyMessageInvalidAsOptionType().MakeReadOnly();
    private static readonly string[] _dummyMessageInvalidAsOptionTypeFieldNames = new string[] {  };
    private static readonly uint[] _dummyMessageInvalidAsOptionTypeFieldTags = new uint[] {  };
    public static DummyMessageInvalidAsOptionType DefaultInstance {
      get { return defaultInstance; }
    }

    public override DummyMessageInvalidAsOptionType DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override DummyMessageInvalidAsOptionType ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<DummyMessageInvalidAsOptionType, DummyMessageInvalidAsOptionType.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_DummyMessageInvalidAsOptionType__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _dummyMessageInvalidAsOptionTypeFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DummyMessageInvalidAsOptionType ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private DummyMessageInvalidAsOptionType MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(DummyMessageInvalidAsOptionType prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<DummyMessageInvalidAsOptionType, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(DummyMessageInvalidAsOptionType cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private DummyMessageInvalidAsOptionType result;

      private DummyMessageInvalidAsOptionType PrepareBuilder() {
        if (resultIsReadOnly) {
          DummyMessageInvalidAsOptionType original = result;
          result = new DummyMessageInvalidAsOptionType();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override DummyMessageInvalidAsOptionType MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType.Descriptor; }
      }

      public override DummyMessageInvalidAsOptionType DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType.DefaultInstance; }
      }

      public override DummyMessageInvalidAsOptionType BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is DummyMessageInvalidAsOptionType) {
          return MergeFrom((DummyMessageInvalidAsOptionType) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(DummyMessageInvalidAsOptionType other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.DummyMessageInvalidAsOptionType.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_dummyMessageInvalidAsOptionTypeFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _dummyMessageInvalidAsOptionTypeFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static DummyMessageInvalidAsOptionType() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionMinIntegerValues : pb::GeneratedMessage<CustomOptionMinIntegerValues, CustomOptionMinIntegerValues.Builder> {
    private CustomOptionMinIntegerValues() { }
    private static readonly CustomOptionMinIntegerValues defaultInstance = new CustomOptionMinIntegerValues().MakeReadOnly();
    private static readonly string[] _customOptionMinIntegerValuesFieldNames = new string[] {  };
    private static readonly uint[] _customOptionMinIntegerValuesFieldTags = new uint[] {  };
    public static CustomOptionMinIntegerValues DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionMinIntegerValues DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionMinIntegerValues ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionMinIntegerValues__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionMinIntegerValues, CustomOptionMinIntegerValues.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionMinIntegerValues__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionMinIntegerValuesFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionMinIntegerValues ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionMinIntegerValues ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionMinIntegerValues MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionMinIntegerValues prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionMinIntegerValues, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionMinIntegerValues cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionMinIntegerValues result;

      private CustomOptionMinIntegerValues PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionMinIntegerValues original = result;
          result = new CustomOptionMinIntegerValues();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionMinIntegerValues MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues.Descriptor; }
      }

      public override CustomOptionMinIntegerValues DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues.DefaultInstance; }
      }

      public override CustomOptionMinIntegerValues BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionMinIntegerValues) {
          return MergeFrom((CustomOptionMinIntegerValues) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionMinIntegerValues other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionMinIntegerValues.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionMinIntegerValuesFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionMinIntegerValuesFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionMinIntegerValues() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionMaxIntegerValues : pb::GeneratedMessage<CustomOptionMaxIntegerValues, CustomOptionMaxIntegerValues.Builder> {
    private CustomOptionMaxIntegerValues() { }
    private static readonly CustomOptionMaxIntegerValues defaultInstance = new CustomOptionMaxIntegerValues().MakeReadOnly();
    private static readonly string[] _customOptionMaxIntegerValuesFieldNames = new string[] {  };
    private static readonly uint[] _customOptionMaxIntegerValuesFieldTags = new uint[] {  };
    public static CustomOptionMaxIntegerValues DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionMaxIntegerValues DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionMaxIntegerValues ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionMaxIntegerValues, CustomOptionMaxIntegerValues.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionMaxIntegerValues__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionMaxIntegerValuesFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionMaxIntegerValues ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionMaxIntegerValues ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionMaxIntegerValues MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionMaxIntegerValues prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionMaxIntegerValues, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionMaxIntegerValues cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionMaxIntegerValues result;

      private CustomOptionMaxIntegerValues PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionMaxIntegerValues original = result;
          result = new CustomOptionMaxIntegerValues();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionMaxIntegerValues MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues.Descriptor; }
      }

      public override CustomOptionMaxIntegerValues DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues.DefaultInstance; }
      }

      public override CustomOptionMaxIntegerValues BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionMaxIntegerValues) {
          return MergeFrom((CustomOptionMaxIntegerValues) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionMaxIntegerValues other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionMaxIntegerValues.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionMaxIntegerValuesFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionMaxIntegerValuesFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionMaxIntegerValues() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class CustomOptionOtherValues : pb::GeneratedMessage<CustomOptionOtherValues, CustomOptionOtherValues.Builder> {
    private CustomOptionOtherValues() { }
    private static readonly CustomOptionOtherValues defaultInstance = new CustomOptionOtherValues().MakeReadOnly();
    private static readonly string[] _customOptionOtherValuesFieldNames = new string[] {  };
    private static readonly uint[] _customOptionOtherValuesFieldTags = new uint[] {  };
    public static CustomOptionOtherValues DefaultInstance {
      get { return defaultInstance; }
    }

    public override CustomOptionOtherValues DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override CustomOptionOtherValues ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionOtherValues__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<CustomOptionOtherValues, CustomOptionOtherValues.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_CustomOptionOtherValues__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _customOptionOtherValuesFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static CustomOptionOtherValues ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static CustomOptionOtherValues ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static CustomOptionOtherValues ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private CustomOptionOtherValues MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(CustomOptionOtherValues prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<CustomOptionOtherValues, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(CustomOptionOtherValues cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private CustomOptionOtherValues result;

      private CustomOptionOtherValues PrepareBuilder() {
        if (resultIsReadOnly) {
          CustomOptionOtherValues original = result;
          result = new CustomOptionOtherValues();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override CustomOptionOtherValues MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues.Descriptor; }
      }

      public override CustomOptionOtherValues DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues.DefaultInstance; }
      }

      public override CustomOptionOtherValues BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is CustomOptionOtherValues) {
          return MergeFrom((CustomOptionOtherValues) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(CustomOptionOtherValues other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.CustomOptionOtherValues.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_customOptionOtherValuesFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _customOptionOtherValuesFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static CustomOptionOtherValues() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class SettingRealsFromPositiveInts : pb::GeneratedMessage<SettingRealsFromPositiveInts, SettingRealsFromPositiveInts.Builder> {
    private SettingRealsFromPositiveInts() { }
    private static readonly SettingRealsFromPositiveInts defaultInstance = new SettingRealsFromPositiveInts().MakeReadOnly();
    private static readonly string[] _settingRealsFromPositiveIntsFieldNames = new string[] {  };
    private static readonly uint[] _settingRealsFromPositiveIntsFieldTags = new uint[] {  };
    public static SettingRealsFromPositiveInts DefaultInstance {
      get { return defaultInstance; }
    }

    public override SettingRealsFromPositiveInts DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override SettingRealsFromPositiveInts ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_SettingRealsFromPositiveInts__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<SettingRealsFromPositiveInts, SettingRealsFromPositiveInts.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_SettingRealsFromPositiveInts__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _settingRealsFromPositiveIntsFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static SettingRealsFromPositiveInts ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SettingRealsFromPositiveInts ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private SettingRealsFromPositiveInts MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(SettingRealsFromPositiveInts prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<SettingRealsFromPositiveInts, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(SettingRealsFromPositiveInts cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private SettingRealsFromPositiveInts result;

      private SettingRealsFromPositiveInts PrepareBuilder() {
        if (resultIsReadOnly) {
          SettingRealsFromPositiveInts original = result;
          result = new SettingRealsFromPositiveInts();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override SettingRealsFromPositiveInts MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts.Descriptor; }
      }

      public override SettingRealsFromPositiveInts DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts.DefaultInstance; }
      }

      public override SettingRealsFromPositiveInts BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is SettingRealsFromPositiveInts) {
          return MergeFrom((SettingRealsFromPositiveInts) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(SettingRealsFromPositiveInts other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.SettingRealsFromPositiveInts.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_settingRealsFromPositiveIntsFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _settingRealsFromPositiveIntsFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static SettingRealsFromPositiveInts() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class SettingRealsFromNegativeInts : pb::GeneratedMessage<SettingRealsFromNegativeInts, SettingRealsFromNegativeInts.Builder> {
    private SettingRealsFromNegativeInts() { }
    private static readonly SettingRealsFromNegativeInts defaultInstance = new SettingRealsFromNegativeInts().MakeReadOnly();
    private static readonly string[] _settingRealsFromNegativeIntsFieldNames = new string[] {  };
    private static readonly uint[] _settingRealsFromNegativeIntsFieldTags = new uint[] {  };
    public static SettingRealsFromNegativeInts DefaultInstance {
      get { return defaultInstance; }
    }

    public override SettingRealsFromNegativeInts DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override SettingRealsFromNegativeInts ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_SettingRealsFromNegativeInts__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<SettingRealsFromNegativeInts, SettingRealsFromNegativeInts.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_SettingRealsFromNegativeInts__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _settingRealsFromNegativeIntsFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static SettingRealsFromNegativeInts ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static SettingRealsFromNegativeInts ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private SettingRealsFromNegativeInts MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(SettingRealsFromNegativeInts prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<SettingRealsFromNegativeInts, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(SettingRealsFromNegativeInts cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private SettingRealsFromNegativeInts result;

      private SettingRealsFromNegativeInts PrepareBuilder() {
        if (resultIsReadOnly) {
          SettingRealsFromNegativeInts original = result;
          result = new SettingRealsFromNegativeInts();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override SettingRealsFromNegativeInts MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts.Descriptor; }
      }

      public override SettingRealsFromNegativeInts DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts.DefaultInstance; }
      }

      public override SettingRealsFromNegativeInts BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is SettingRealsFromNegativeInts) {
          return MergeFrom((SettingRealsFromNegativeInts) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(SettingRealsFromNegativeInts other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.SettingRealsFromNegativeInts.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_settingRealsFromNegativeIntsFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _settingRealsFromNegativeIntsFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static SettingRealsFromNegativeInts() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class ComplexOptionType1 : pb::ExtendableMessage<ComplexOptionType1, ComplexOptionType1.Builder> {
    private ComplexOptionType1() { }
    private static readonly ComplexOptionType1 defaultInstance = new ComplexOptionType1().MakeReadOnly();
    private static readonly string[] _complexOptionType1FieldNames = new string[] { "foo", "foo2", "foo3", "foo4" };
    private static readonly uint[] _complexOptionType1FieldTags = new uint[] { 8, 16, 24, 32 };
    public static ComplexOptionType1 DefaultInstance {
      get { return defaultInstance; }
    }

    public override ComplexOptionType1 DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override ComplexOptionType1 ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType1__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<ComplexOptionType1, ComplexOptionType1.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType1__FieldAccessorTable; }
    }

    public const int FooFieldNumber = 1;
    private bool hasFoo;
    private int foo_;
    public bool HasFoo {
      get { return hasFoo; }
    }
    public int Foo {
      get { return foo_; }
    }

    public const int Foo2FieldNumber = 2;
    private bool hasFoo2;
    private int foo2_;
    public bool HasFoo2 {
      get { return hasFoo2; }
    }
    public int Foo2 {
      get { return foo2_; }
    }

    public const int Foo3FieldNumber = 3;
    private bool hasFoo3;
    private int foo3_;
    public bool HasFoo3 {
      get { return hasFoo3; }
    }
    public int Foo3 {
      get { return foo3_; }
    }

    public const int Foo4FieldNumber = 4;
    private pbc::PopsicleList<int> foo4_ = new pbc::PopsicleList<int>();
    public scg::IList<int> Foo4List {
      get { return pbc::Lists.AsReadOnly(foo4_); }
    }
    public int Foo4Count {
      get { return foo4_.Count; }
    }
    public int GetFoo4(int index) {
      return foo4_[index];
    }

    public override bool IsInitialized {
      get {
        if (!ExtensionsAreInitialized) return false;
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _complexOptionType1FieldNames;
      pb::ExtendableMessage<ComplexOptionType1, ComplexOptionType1.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      if (hasFoo) {
        output.WriteInt32(1, field_names[0], Foo);
      }
      if (hasFoo2) {
        output.WriteInt32(2, field_names[1], Foo2);
      }
      if (hasFoo3) {
        output.WriteInt32(3, field_names[2], Foo3);
      }
      if (foo4_.Count > 0) {
        output.WriteInt32Array(4, field_names[3], foo4_);
      }
      extensionWriter.WriteUntil(536870912, output);
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasFoo) {
        size += pb::CodedOutputStream.ComputeInt32Size(1, Foo);
      }
      if (hasFoo2) {
        size += pb::CodedOutputStream.ComputeInt32Size(2, Foo2);
      }
      if (hasFoo3) {
        size += pb::CodedOutputStream.ComputeInt32Size(3, Foo3);
      }
      {
        int dataSize = 0;
        foreach (int element in Foo4List) {
          dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
        }
        size += dataSize;
        size += 1 * foo4_.Count;
      }
      size += ExtensionsSerializedSize;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static ComplexOptionType1 ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType1 ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static ComplexOptionType1 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOptionType1 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private ComplexOptionType1 MakeReadOnly() {
      foo4_.MakeReadOnly();
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(ComplexOptionType1 prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::ExtendableBuilder<ComplexOptionType1, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(ComplexOptionType1 cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private ComplexOptionType1 result;

      private ComplexOptionType1 PrepareBuilder() {
        if (resultIsReadOnly) {
          ComplexOptionType1 original = result;
          result = new ComplexOptionType1();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override ComplexOptionType1 MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.Descriptor; }
      }

      public override ComplexOptionType1 DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.DefaultInstance; }
      }

      public override ComplexOptionType1 BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is ComplexOptionType1) {
          return MergeFrom((ComplexOptionType1) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(ComplexOptionType1 other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasFoo) {
          Foo = other.Foo;
        }
        if (other.HasFoo2) {
          Foo2 = other.Foo2;
        }
        if (other.HasFoo3) {
          Foo3 = other.Foo3;
        }
        if (other.foo4_.Count != 0) {
          result.foo4_.Add(other.foo4_);
        }
          this.MergeExtensionFields(other);
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_complexOptionType1FieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _complexOptionType1FieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasFoo = input.ReadInt32(ref result.foo_);
              break;
            }
            case 16: {
              result.hasFoo2 = input.ReadInt32(ref result.foo2_);
              break;
            }
            case 24: {
              result.hasFoo3 = input.ReadInt32(ref result.foo3_);
              break;
            }
            case 34:
            case 32: {
              input.ReadInt32Array(tag, field_name, result.foo4_);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasFoo {
        get { return result.hasFoo; }
      }
      public int Foo {
        get { return result.Foo; }
        set { SetFoo(value); }
      }
      public Builder SetFoo(int value) {
        PrepareBuilder();
        result.hasFoo = true;
        result.foo_ = value;
        return this;
      }
      public Builder ClearFoo() {
        PrepareBuilder();
        result.hasFoo = false;
        result.foo_ = 0;
        return this;
      }

      public bool HasFoo2 {
        get { return result.hasFoo2; }
      }
      public int Foo2 {
        get { return result.Foo2; }
        set { SetFoo2(value); }
      }
      public Builder SetFoo2(int value) {
        PrepareBuilder();
        result.hasFoo2 = true;
        result.foo2_ = value;
        return this;
      }
      public Builder ClearFoo2() {
        PrepareBuilder();
        result.hasFoo2 = false;
        result.foo2_ = 0;
        return this;
      }

      public bool HasFoo3 {
        get { return result.hasFoo3; }
      }
      public int Foo3 {
        get { return result.Foo3; }
        set { SetFoo3(value); }
      }
      public Builder SetFoo3(int value) {
        PrepareBuilder();
        result.hasFoo3 = true;
        result.foo3_ = value;
        return this;
      }
      public Builder ClearFoo3() {
        PrepareBuilder();
        result.hasFoo3 = false;
        result.foo3_ = 0;
        return this;
      }

      public pbc::IPopsicleList<int> Foo4List {
        get { return PrepareBuilder().foo4_; }
      }
      public int Foo4Count {
        get { return result.Foo4Count; }
      }
      public int GetFoo4(int index) {
        return result.GetFoo4(index);
      }
      public Builder SetFoo4(int index, int value) {
        PrepareBuilder();
        result.foo4_[index] = value;
        return this;
      }
      public Builder AddFoo4(int value) {
        PrepareBuilder();
        result.foo4_.Add(value);
        return this;
      }
      public Builder AddRangeFoo4(scg::IEnumerable<int> values) {
        PrepareBuilder();
        result.foo4_.Add(values);
        return this;
      }
      public Builder ClearFoo4() {
        PrepareBuilder();
        result.foo4_.Clear();
        return this;
      }
    }
    static ComplexOptionType1() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class ComplexOptionType2 : pb::ExtendableMessage<ComplexOptionType2, ComplexOptionType2.Builder> {
    private ComplexOptionType2() { }
    private static readonly ComplexOptionType2 defaultInstance = new ComplexOptionType2().MakeReadOnly();
    private static readonly string[] _complexOptionType2FieldNames = new string[] { "bar", "barney", "baz", "fred" };
    private static readonly uint[] _complexOptionType2FieldTags = new uint[] { 10, 34, 16, 26 };
    public static ComplexOptionType2 DefaultInstance {
      get { return defaultInstance; }
    }

    public override ComplexOptionType2 DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override ComplexOptionType2 ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType2__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<ComplexOptionType2, ComplexOptionType2.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType2__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class ComplexOptionType4 : pb::GeneratedMessage<ComplexOptionType4, ComplexOptionType4.Builder> {
        private ComplexOptionType4() { }
        private static readonly ComplexOptionType4 defaultInstance = new ComplexOptionType4().MakeReadOnly();
        private static readonly string[] _complexOptionType4FieldNames = new string[] { "waldo" };
        private static readonly uint[] _complexOptionType4FieldTags = new uint[] { 8 };
        public static ComplexOptionType4 DefaultInstance {
          get { return defaultInstance; }
        }

        public override ComplexOptionType4 DefaultInstanceForType {
          get { return DefaultInstance; }
        }

        protected override ComplexOptionType4 ThisMessage {
          get { return this; }
        }

        public static pbd::MessageDescriptor Descriptor {
          get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__Descriptor; }
        }

        protected override pb::FieldAccess.FieldAccessorTable<ComplexOptionType4, ComplexOptionType4.Builder> InternalFieldAccessors {
          get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType2_ComplexOptionType4__FieldAccessorTable; }
        }

        public const int ComplexOpt4FieldNumber = 7633546;
        public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> ComplexOpt4;
        public const int WaldoFieldNumber = 1;
        private bool hasWaldo;
        private int waldo_;
        public bool HasWaldo {
          get { return hasWaldo; }
        }
        public int Waldo {
          get { return waldo_; }
        }

        public override bool IsInitialized {
          get {
            return true;
          }
        }

        public override void WriteTo(pb::ICodedOutputStream output) {
          CalcSerializedSize();
          string[] field_names = _complexOptionType4FieldNames;
          if (hasWaldo) {
            output.WriteInt32(1, field_names[0], Waldo);
          }
          UnknownFields.WriteTo(output);
        }

        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            int size = memoizedSerializedSize;
            if (size != -1) return size;
            return CalcSerializedSize();
          }
        }

        private int CalcSerializedSize() {
          int size = memoizedSerializedSize;
          if (size != -1) return size;

          size = 0;
          if (hasWaldo) {
            size += pb::CodedOutputStream.ComputeInt32Size(1, Waldo);
          }
          size += UnknownFields.SerializedSize;
          memoizedSerializedSize = size;
          return size;
        }
        public static ComplexOptionType4 ParseFrom(pb::ByteString data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(byte[] data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(global::System.IO.Stream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        public static ComplexOptionType4 ParseDelimitedFrom(global::System.IO.Stream input) {
          return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
        }
        public static ComplexOptionType4 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(pb::ICodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static ComplexOptionType4 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        private ComplexOptionType4 MakeReadOnly() {
          return this;
        }

        public static Builder CreateBuilder() { return new Builder(); }
        public override Builder ToBuilder() { return CreateBuilder(this); }
        public override Builder CreateBuilderForType() { return new Builder(); }
        public static Builder CreateBuilder(ComplexOptionType4 prototype) {
          return new Builder(prototype);
        }

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public sealed partial class Builder : pb::GeneratedBuilder<ComplexOptionType4, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {
            result = DefaultInstance;
            resultIsReadOnly = true;
          }
          internal Builder(ComplexOptionType4 cloneFrom) {
            result = cloneFrom;
            resultIsReadOnly = true;
          }

          private bool resultIsReadOnly;
          private ComplexOptionType4 result;

          private ComplexOptionType4 PrepareBuilder() {
            if (resultIsReadOnly) {
              ComplexOptionType4 original = result;
              result = new ComplexOptionType4();
              resultIsReadOnly = false;
              MergeFrom(original);
            }
            return result;
          }

          public override bool IsInitialized {
            get { return result.IsInitialized; }
          }

          protected override ComplexOptionType4 MessageBeingBuilt {
            get { return PrepareBuilder(); }
          }

          public override Builder Clear() {
            result = DefaultInstance;
            resultIsReadOnly = true;
            return this;
          }

          public override Builder Clone() {
            if (resultIsReadOnly) {
              return new Builder(result);
            } else {
              return new Builder().MergeFrom(result);
            }
          }

          public override pbd::MessageDescriptor DescriptorForType {
            get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Descriptor; }
          }

          public override ComplexOptionType4 DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.DefaultInstance; }
          }

          public override ComplexOptionType4 BuildPartial() {
            if (resultIsReadOnly) {
              return result;
            }
            resultIsReadOnly = true;
            return result.MakeReadOnly();
          }

          public override Builder MergeFrom(pb::IMessage other) {
            if (other is ComplexOptionType4) {
              return MergeFrom((ComplexOptionType4) other);
            } else {
              base.MergeFrom(other);
              return this;
            }
          }

          public override Builder MergeFrom(ComplexOptionType4 other) {
            if (other == global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.DefaultInstance) return this;
            PrepareBuilder();
            if (other.HasWaldo) {
              Waldo = other.Waldo;
            }
            this.MergeUnknownFields(other.UnknownFields);
            return this;
          }

          public override Builder MergeFrom(pb::ICodedInputStream input) {
            return MergeFrom(input, pb::ExtensionRegistry.Empty);
          }

          public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            PrepareBuilder();
            pb::UnknownFieldSet.Builder unknownFields = null;
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              if(tag == 0 && field_name != null) {
                int field_ordinal = global::System.Array.BinarySearch(_complexOptionType4FieldNames, field_name, global::System.StringComparer.Ordinal);
                if(field_ordinal >= 0)
                  tag = _complexOptionType4FieldTags[field_ordinal];
                else {
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  continue;
                }
              }
              switch (tag) {
                case 0: {
                  throw pb::InvalidProtocolBufferException.InvalidTag();
                }
                default: {
                  if (pb::WireFormat.IsEndGroupTag(tag)) {
                    if (unknownFields != null) {
                      this.UnknownFields = unknownFields.Build();
                    }
                    return this;
                  }
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  break;
                }
                case 8: {
                  result.hasWaldo = input.ReadInt32(ref result.waldo_);
                  break;
                }
              }
            }

            if (unknownFields != null) {
              this.UnknownFields = unknownFields.Build();
            }
            return this;
          }


          public bool HasWaldo {
            get { return result.hasWaldo; }
          }
          public int Waldo {
            get { return result.Waldo; }
            set { SetWaldo(value); }
          }
          public Builder SetWaldo(int value) {
            PrepareBuilder();
            result.hasWaldo = true;
            result.waldo_ = value;
            return this;
          }
          public Builder ClearWaldo() {
            PrepareBuilder();
            result.hasWaldo = false;
            result.waldo_ = 0;
            return this;
          }
        }
        static ComplexOptionType4() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
        }
      }

    }
    #endregion

    public const int BarFieldNumber = 1;
    private bool hasBar;
    private global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1 bar_;
    public bool HasBar {
      get { return hasBar; }
    }
    public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1 Bar {
      get { return bar_ ?? global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.DefaultInstance; }
    }

    public const int BazFieldNumber = 2;
    private bool hasBaz;
    private int baz_;
    public bool HasBaz {
      get { return hasBaz; }
    }
    public int Baz {
      get { return baz_; }
    }

    public const int FredFieldNumber = 3;
    private bool hasFred;
    private global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 fred_;
    public bool HasFred {
      get { return hasFred; }
    }
    public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 Fred {
      get { return fred_ ?? global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.DefaultInstance; }
    }

    public const int BarneyFieldNumber = 4;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> barney_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> BarneyList {
      get { return barney_; }
    }
    public int BarneyCount {
      get { return barney_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 GetBarney(int index) {
      return barney_[index];
    }

    public override bool IsInitialized {
      get {
        if (HasFred) {
          if (!Fred.IsInitialized) return false;
        }
        foreach (global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 element in BarneyList) {
          if (!element.IsInitialized) return false;
        }
        if (!ExtensionsAreInitialized) return false;
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _complexOptionType2FieldNames;
      pb::ExtendableMessage<ComplexOptionType2, ComplexOptionType2.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      if (hasBar) {
        output.WriteMessage(1, field_names[0], Bar);
      }
      if (hasBaz) {
        output.WriteInt32(2, field_names[2], Baz);
      }
      if (hasFred) {
        output.WriteMessage(3, field_names[3], Fred);
      }
      if (barney_.Count > 0) {
        output.WriteMessageArray(4, field_names[1], barney_);
      }
      extensionWriter.WriteUntil(536870912, output);
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasBar) {
        size += pb::CodedOutputStream.ComputeMessageSize(1, Bar);
      }
      if (hasBaz) {
        size += pb::CodedOutputStream.ComputeInt32Size(2, Baz);
      }
      if (hasFred) {
        size += pb::CodedOutputStream.ComputeMessageSize(3, Fred);
      }
      foreach (global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 element in BarneyList) {
        size += pb::CodedOutputStream.ComputeMessageSize(4, element);
      }
      size += ExtensionsSerializedSize;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static ComplexOptionType2 ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType2 ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static ComplexOptionType2 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOptionType2 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private ComplexOptionType2 MakeReadOnly() {
      barney_.MakeReadOnly();
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(ComplexOptionType2 prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::ExtendableBuilder<ComplexOptionType2, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(ComplexOptionType2 cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private ComplexOptionType2 result;

      private ComplexOptionType2 PrepareBuilder() {
        if (resultIsReadOnly) {
          ComplexOptionType2 original = result;
          result = new ComplexOptionType2();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override ComplexOptionType2 MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Descriptor; }
      }

      public override ComplexOptionType2 DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.DefaultInstance; }
      }

      public override ComplexOptionType2 BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is ComplexOptionType2) {
          return MergeFrom((ComplexOptionType2) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(ComplexOptionType2 other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasBar) {
          MergeBar(other.Bar);
        }
        if (other.HasBaz) {
          Baz = other.Baz;
        }
        if (other.HasFred) {
          MergeFred(other.Fred);
        }
        if (other.barney_.Count != 0) {
          result.barney_.Add(other.barney_);
        }
          this.MergeExtensionFields(other);
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_complexOptionType2FieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _complexOptionType2FieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 10: {
              global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.CreateBuilder();
              if (result.hasBar) {
                subBuilder.MergeFrom(Bar);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              Bar = subBuilder.BuildPartial();
              break;
            }
            case 16: {
              result.hasBaz = input.ReadInt32(ref result.baz_);
              break;
            }
            case 26: {
              global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.CreateBuilder();
              if (result.hasFred) {
                subBuilder.MergeFrom(Fred);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              Fred = subBuilder.BuildPartial();
              break;
            }
            case 34: {
              input.ReadMessageArray(tag, field_name, result.barney_, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.DefaultInstance, extensionRegistry);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasBar {
       get { return result.hasBar; }
      }
      public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1 Bar {
        get { return result.Bar; }
        set { SetBar(value); }
      }
      public Builder SetBar(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasBar = true;
        result.bar_ = value;
        return this;
      }
      public Builder SetBar(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasBar = true;
        result.bar_ = builderForValue.Build();
        return this;
      }
      public Builder MergeBar(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasBar &&
            result.bar_ != global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.DefaultInstance) {
            result.bar_ = global::Google.ProtocolBuffers.TestProtos.ComplexOptionType1.CreateBuilder(result.bar_).MergeFrom(value).BuildPartial();
        } else {
          result.bar_ = value;
        }
        result.hasBar = true;
        return this;
      }
      public Builder ClearBar() {
        PrepareBuilder();
        result.hasBar = false;
        result.bar_ = null;
        return this;
      }

      public bool HasBaz {
        get { return result.hasBaz; }
      }
      public int Baz {
        get { return result.Baz; }
        set { SetBaz(value); }
      }
      public Builder SetBaz(int value) {
        PrepareBuilder();
        result.hasBaz = true;
        result.baz_ = value;
        return this;
      }
      public Builder ClearBaz() {
        PrepareBuilder();
        result.hasBaz = false;
        result.baz_ = 0;
        return this;
      }

      public bool HasFred {
       get { return result.hasFred; }
      }
      public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 Fred {
        get { return result.Fred; }
        set { SetFred(value); }
      }
      public Builder SetFred(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasFred = true;
        result.fred_ = value;
        return this;
      }
      public Builder SetFred(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasFred = true;
        result.fred_ = builderForValue.Build();
        return this;
      }
      public Builder MergeFred(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasFred &&
            result.fred_ != global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.DefaultInstance) {
            result.fred_ = global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.CreateBuilder(result.fred_).MergeFrom(value).BuildPartial();
        } else {
          result.fred_ = value;
        }
        result.hasFred = true;
        return this;
      }
      public Builder ClearFred() {
        PrepareBuilder();
        result.hasFred = false;
        result.fred_ = null;
        return this;
      }

      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> BarneyList {
        get { return PrepareBuilder().barney_; }
      }
      public int BarneyCount {
        get { return result.BarneyCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 GetBarney(int index) {
        return result.GetBarney(index);
      }
      public Builder SetBarney(int index, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.barney_[index] = value;
        return this;
      }
      public Builder SetBarney(int index, global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.barney_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddBarney(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.barney_.Add(value);
        return this;
      }
      public Builder AddBarney(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.barney_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangeBarney(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.ComplexOptionType2.Types.ComplexOptionType4> values) {
        PrepareBuilder();
        result.barney_.Add(values);
        return this;
      }
      public Builder ClearBarney() {
        PrepareBuilder();
        result.barney_.Clear();
        return this;
      }
    }
    static ComplexOptionType2() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class ComplexOptionType3 : pb::GeneratedMessage<ComplexOptionType3, ComplexOptionType3.Builder> {
    private ComplexOptionType3() { }
    private static readonly ComplexOptionType3 defaultInstance = new ComplexOptionType3().MakeReadOnly();
    private static readonly string[] _complexOptionType3FieldNames = new string[] { "complexoptiontype5", "qux" };
    private static readonly uint[] _complexOptionType3FieldTags = new uint[] { 19, 8 };
    public static ComplexOptionType3 DefaultInstance {
      get { return defaultInstance; }
    }

    public override ComplexOptionType3 DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override ComplexOptionType3 ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType3__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<ComplexOptionType3, ComplexOptionType3.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType3__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class ComplexOptionType5 : pb::GeneratedMessage<ComplexOptionType5, ComplexOptionType5.Builder> {
        private ComplexOptionType5() { }
        private static readonly ComplexOptionType5 defaultInstance = new ComplexOptionType5().MakeReadOnly();
        private static readonly string[] _complexOptionType5FieldNames = new string[] { "plugh" };
        private static readonly uint[] _complexOptionType5FieldTags = new uint[] { 24 };
        public static ComplexOptionType5 DefaultInstance {
          get { return defaultInstance; }
        }

        public override ComplexOptionType5 DefaultInstanceForType {
          get { return DefaultInstance; }
        }

        protected override ComplexOptionType5 ThisMessage {
          get { return this; }
        }

        public static pbd::MessageDescriptor Descriptor {
          get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__Descriptor; }
        }

        protected override pb::FieldAccess.FieldAccessorTable<ComplexOptionType5, ComplexOptionType5.Builder> InternalFieldAccessors {
          get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOptionType3_ComplexOptionType5__FieldAccessorTable; }
        }

        public const int PlughFieldNumber = 3;
        private bool hasPlugh;
        private int plugh_;
        public bool HasPlugh {
          get { return hasPlugh; }
        }
        public int Plugh {
          get { return plugh_; }
        }

        public override bool IsInitialized {
          get {
            return true;
          }
        }

        public override void WriteTo(pb::ICodedOutputStream output) {
          CalcSerializedSize();
          string[] field_names = _complexOptionType5FieldNames;
          if (hasPlugh) {
            output.WriteInt32(3, field_names[0], Plugh);
          }
          UnknownFields.WriteTo(output);
        }

        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            int size = memoizedSerializedSize;
            if (size != -1) return size;
            return CalcSerializedSize();
          }
        }

        private int CalcSerializedSize() {
          int size = memoizedSerializedSize;
          if (size != -1) return size;

          size = 0;
          if (hasPlugh) {
            size += pb::CodedOutputStream.ComputeInt32Size(3, Plugh);
          }
          size += UnknownFields.SerializedSize;
          memoizedSerializedSize = size;
          return size;
        }
        public static ComplexOptionType5 ParseFrom(pb::ByteString data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(byte[] data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(global::System.IO.Stream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        public static ComplexOptionType5 ParseDelimitedFrom(global::System.IO.Stream input) {
          return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
        }
        public static ComplexOptionType5 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(pb::ICodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static ComplexOptionType5 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        private ComplexOptionType5 MakeReadOnly() {
          return this;
        }

        public static Builder CreateBuilder() { return new Builder(); }
        public override Builder ToBuilder() { return CreateBuilder(this); }
        public override Builder CreateBuilderForType() { return new Builder(); }
        public static Builder CreateBuilder(ComplexOptionType5 prototype) {
          return new Builder(prototype);
        }

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public sealed partial class Builder : pb::GeneratedBuilder<ComplexOptionType5, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {
            result = DefaultInstance;
            resultIsReadOnly = true;
          }
          internal Builder(ComplexOptionType5 cloneFrom) {
            result = cloneFrom;
            resultIsReadOnly = true;
          }

          private bool resultIsReadOnly;
          private ComplexOptionType5 result;

          private ComplexOptionType5 PrepareBuilder() {
            if (resultIsReadOnly) {
              ComplexOptionType5 original = result;
              result = new ComplexOptionType5();
              resultIsReadOnly = false;
              MergeFrom(original);
            }
            return result;
          }

          public override bool IsInitialized {
            get { return result.IsInitialized; }
          }

          protected override ComplexOptionType5 MessageBeingBuilt {
            get { return PrepareBuilder(); }
          }

          public override Builder Clear() {
            result = DefaultInstance;
            resultIsReadOnly = true;
            return this;
          }

          public override Builder Clone() {
            if (resultIsReadOnly) {
              return new Builder(result);
            } else {
              return new Builder().MergeFrom(result);
            }
          }

          public override pbd::MessageDescriptor DescriptorForType {
            get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.Descriptor; }
          }

          public override ComplexOptionType5 DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.DefaultInstance; }
          }

          public override ComplexOptionType5 BuildPartial() {
            if (resultIsReadOnly) {
              return result;
            }
            resultIsReadOnly = true;
            return result.MakeReadOnly();
          }

          public override Builder MergeFrom(pb::IMessage other) {
            if (other is ComplexOptionType5) {
              return MergeFrom((ComplexOptionType5) other);
            } else {
              base.MergeFrom(other);
              return this;
            }
          }

          public override Builder MergeFrom(ComplexOptionType5 other) {
            if (other == global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.DefaultInstance) return this;
            PrepareBuilder();
            if (other.HasPlugh) {
              Plugh = other.Plugh;
            }
            this.MergeUnknownFields(other.UnknownFields);
            return this;
          }

          public override Builder MergeFrom(pb::ICodedInputStream input) {
            return MergeFrom(input, pb::ExtensionRegistry.Empty);
          }

          public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            PrepareBuilder();
            pb::UnknownFieldSet.Builder unknownFields = null;
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              if(tag == 0 && field_name != null) {
                int field_ordinal = global::System.Array.BinarySearch(_complexOptionType5FieldNames, field_name, global::System.StringComparer.Ordinal);
                if(field_ordinal >= 0)
                  tag = _complexOptionType5FieldTags[field_ordinal];
                else {
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  continue;
                }
              }
              switch (tag) {
                case 0: {
                  throw pb::InvalidProtocolBufferException.InvalidTag();
                }
                default: {
                  if (pb::WireFormat.IsEndGroupTag(tag)) {
                    if (unknownFields != null) {
                      this.UnknownFields = unknownFields.Build();
                    }
                    return this;
                  }
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  break;
                }
                case 24: {
                  result.hasPlugh = input.ReadInt32(ref result.plugh_);
                  break;
                }
              }
            }

            if (unknownFields != null) {
              this.UnknownFields = unknownFields.Build();
            }
            return this;
          }


          public bool HasPlugh {
            get { return result.hasPlugh; }
          }
          public int Plugh {
            get { return result.Plugh; }
            set { SetPlugh(value); }
          }
          public Builder SetPlugh(int value) {
            PrepareBuilder();
            result.hasPlugh = true;
            result.plugh_ = value;
            return this;
          }
          public Builder ClearPlugh() {
            PrepareBuilder();
            result.hasPlugh = false;
            result.plugh_ = 0;
            return this;
          }
        }
        static ComplexOptionType5() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
        }
      }

    }
    #endregion

    public const int QuxFieldNumber = 1;
    private bool hasQux;
    private int qux_;
    public bool HasQux {
      get { return hasQux; }
    }
    public int Qux {
      get { return qux_; }
    }

    public const int ComplexOptionType5FieldNumber = 2;
    private bool hasComplexOptionType5;
    private global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5 complexOptionType5_;
    public bool HasComplexOptionType5 {
      get { return hasComplexOptionType5; }
    }
    public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5 ComplexOptionType5 {
      get { return complexOptionType5_ ?? global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.DefaultInstance; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _complexOptionType3FieldNames;
      if (hasQux) {
        output.WriteInt32(1, field_names[1], Qux);
      }
      if (hasComplexOptionType5) {
        output.WriteGroup(2, field_names[0], ComplexOptionType5);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasQux) {
        size += pb::CodedOutputStream.ComputeInt32Size(1, Qux);
      }
      if (hasComplexOptionType5) {
        size += pb::CodedOutputStream.ComputeGroupSize(2, ComplexOptionType5);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static ComplexOptionType3 ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static ComplexOptionType3 ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static ComplexOptionType3 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOptionType3 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private ComplexOptionType3 MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(ComplexOptionType3 prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<ComplexOptionType3, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(ComplexOptionType3 cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private ComplexOptionType3 result;

      private ComplexOptionType3 PrepareBuilder() {
        if (resultIsReadOnly) {
          ComplexOptionType3 original = result;
          result = new ComplexOptionType3();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override ComplexOptionType3 MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Descriptor; }
      }

      public override ComplexOptionType3 DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.DefaultInstance; }
      }

      public override ComplexOptionType3 BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is ComplexOptionType3) {
          return MergeFrom((ComplexOptionType3) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(ComplexOptionType3 other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasQux) {
          Qux = other.Qux;
        }
        if (other.HasComplexOptionType5) {
          MergeComplexOptionType5(other.ComplexOptionType5);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_complexOptionType3FieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _complexOptionType3FieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasQux = input.ReadInt32(ref result.qux_);
              break;
            }
            case 19: {
              global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.CreateBuilder();
              if (result.hasComplexOptionType5) {
                subBuilder.MergeFrom(ComplexOptionType5);
              }
              input.ReadGroup(2, subBuilder, extensionRegistry);
              ComplexOptionType5 = subBuilder.BuildPartial();
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasQux {
        get { return result.hasQux; }
      }
      public int Qux {
        get { return result.Qux; }
        set { SetQux(value); }
      }
      public Builder SetQux(int value) {
        PrepareBuilder();
        result.hasQux = true;
        result.qux_ = value;
        return this;
      }
      public Builder ClearQux() {
        PrepareBuilder();
        result.hasQux = false;
        result.qux_ = 0;
        return this;
      }

      public bool HasComplexOptionType5 {
       get { return result.hasComplexOptionType5; }
      }
      public global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5 ComplexOptionType5 {
        get { return result.ComplexOptionType5; }
        set { SetComplexOptionType5(value); }
      }
      public Builder SetComplexOptionType5(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasComplexOptionType5 = true;
        result.complexOptionType5_ = value;
        return this;
      }
      public Builder SetComplexOptionType5(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasComplexOptionType5 = true;
        result.complexOptionType5_ = builderForValue.Build();
        return this;
      }
      public Builder MergeComplexOptionType5(global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5 value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasComplexOptionType5 &&
            result.complexOptionType5_ != global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.DefaultInstance) {
            result.complexOptionType5_ = global::Google.ProtocolBuffers.TestProtos.ComplexOptionType3.Types.ComplexOptionType5.CreateBuilder(result.complexOptionType5_).MergeFrom(value).BuildPartial();
        } else {
          result.complexOptionType5_ = value;
        }
        result.hasComplexOptionType5 = true;
        return this;
      }
      public Builder ClearComplexOptionType5() {
        PrepareBuilder();
        result.hasComplexOptionType5 = false;
        result.complexOptionType5_ = null;
        return this;
      }
    }
    static ComplexOptionType3() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class ComplexOpt6 : pb::GeneratedMessage<ComplexOpt6, ComplexOpt6.Builder> {
    private ComplexOpt6() { }
    private static readonly ComplexOpt6 defaultInstance = new ComplexOpt6().MakeReadOnly();
    private static readonly string[] _complexOpt6FieldNames = new string[] { "xyzzy" };
    private static readonly uint[] _complexOpt6FieldTags = new uint[] { 60751608 };
    public static ComplexOpt6 DefaultInstance {
      get { return defaultInstance; }
    }

    public override ComplexOpt6 DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override ComplexOpt6 ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOpt6__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<ComplexOpt6, ComplexOpt6.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_ComplexOpt6__FieldAccessorTable; }
    }

    public const int XyzzyFieldNumber = 7593951;
    private bool hasXyzzy;
    private int xyzzy_;
    public bool HasXyzzy {
      get { return hasXyzzy; }
    }
    public int Xyzzy {
      get { return xyzzy_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _complexOpt6FieldNames;
      if (hasXyzzy) {
        output.WriteInt32(7593951, field_names[0], Xyzzy);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasXyzzy) {
        size += pb::CodedOutputStream.ComputeInt32Size(7593951, Xyzzy);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static ComplexOpt6 ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static ComplexOpt6 ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static ComplexOpt6 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static ComplexOpt6 ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private ComplexOpt6 MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(ComplexOpt6 prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<ComplexOpt6, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(ComplexOpt6 cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private ComplexOpt6 result;

      private ComplexOpt6 PrepareBuilder() {
        if (resultIsReadOnly) {
          ComplexOpt6 original = result;
          result = new ComplexOpt6();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override ComplexOpt6 MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOpt6.Descriptor; }
      }

      public override ComplexOpt6 DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.ComplexOpt6.DefaultInstance; }
      }

      public override ComplexOpt6 BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is ComplexOpt6) {
          return MergeFrom((ComplexOpt6) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(ComplexOpt6 other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.ComplexOpt6.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasXyzzy) {
          Xyzzy = other.Xyzzy;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_complexOpt6FieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _complexOpt6FieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 60751608: {
              result.hasXyzzy = input.ReadInt32(ref result.xyzzy_);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasXyzzy {
        get { return result.hasXyzzy; }
      }
      public int Xyzzy {
        get { return result.Xyzzy; }
        set { SetXyzzy(value); }
      }
      public Builder SetXyzzy(int value) {
        PrepareBuilder();
        result.hasXyzzy = true;
        result.xyzzy_ = value;
        return this;
      }
      public Builder ClearXyzzy() {
        PrepareBuilder();
        result.hasXyzzy = false;
        result.xyzzy_ = 0;
        return this;
      }
    }
    static ComplexOpt6() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class VariousComplexOptions : pb::GeneratedMessage<VariousComplexOptions, VariousComplexOptions.Builder> {
    private VariousComplexOptions() { }
    private static readonly VariousComplexOptions defaultInstance = new VariousComplexOptions().MakeReadOnly();
    private static readonly string[] _variousComplexOptionsFieldNames = new string[] {  };
    private static readonly uint[] _variousComplexOptionsFieldTags = new uint[] {  };
    public static VariousComplexOptions DefaultInstance {
      get { return defaultInstance; }
    }

    public override VariousComplexOptions DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override VariousComplexOptions ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_VariousComplexOptions__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<VariousComplexOptions, VariousComplexOptions.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_VariousComplexOptions__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _variousComplexOptionsFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static VariousComplexOptions ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static VariousComplexOptions ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static VariousComplexOptions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static VariousComplexOptions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private VariousComplexOptions MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(VariousComplexOptions prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<VariousComplexOptions, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(VariousComplexOptions cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private VariousComplexOptions result;

      private VariousComplexOptions PrepareBuilder() {
        if (resultIsReadOnly) {
          VariousComplexOptions original = result;
          result = new VariousComplexOptions();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override VariousComplexOptions MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions.Descriptor; }
      }

      public override VariousComplexOptions DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions.DefaultInstance; }
      }

      public override VariousComplexOptions BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is VariousComplexOptions) {
          return MergeFrom((VariousComplexOptions) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(VariousComplexOptions other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.VariousComplexOptions.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_variousComplexOptionsFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _variousComplexOptionsFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static VariousComplexOptions() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class AggregateMessageSet : pb::ExtendableMessage<AggregateMessageSet, AggregateMessageSet.Builder> {
    private AggregateMessageSet() { }
    private static readonly AggregateMessageSet defaultInstance = new AggregateMessageSet().MakeReadOnly();
    private static readonly string[] _aggregateMessageSetFieldNames = new string[] {  };
    private static readonly uint[] _aggregateMessageSetFieldTags = new uint[] {  };
    public static AggregateMessageSet DefaultInstance {
      get { return defaultInstance; }
    }

    public override AggregateMessageSet DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override AggregateMessageSet ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_AggregateMessageSet__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<AggregateMessageSet, AggregateMessageSet.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_AggregateMessageSet__FieldAccessorTable; }
    }

    public override bool IsInitialized {
      get {
        if (!ExtensionsAreInitialized) return false;
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _aggregateMessageSetFieldNames;
      pb::ExtendableMessage<AggregateMessageSet, AggregateMessageSet.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      extensionWriter.WriteUntil(2147483647, output);
      UnknownFields.WriteAsMessageSetTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += ExtensionsSerializedSize;
      size += UnknownFields.SerializedSizeAsMessageSet;
      memoizedSerializedSize = size;
      return size;
    }
    public static AggregateMessageSet ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessageSet ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static AggregateMessageSet ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AggregateMessageSet ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private AggregateMessageSet MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(AggregateMessageSet prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::ExtendableBuilder<AggregateMessageSet, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(AggregateMessageSet cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private AggregateMessageSet result;

      private AggregateMessageSet PrepareBuilder() {
        if (resultIsReadOnly) {
          AggregateMessageSet original = result;
          result = new AggregateMessageSet();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override AggregateMessageSet MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.Descriptor; }
      }

      public override AggregateMessageSet DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.DefaultInstance; }
      }

      public override AggregateMessageSet BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is AggregateMessageSet) {
          return MergeFrom((AggregateMessageSet) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(AggregateMessageSet other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.DefaultInstance) return this;
        PrepareBuilder();
          this.MergeExtensionFields(other);
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_aggregateMessageSetFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _aggregateMessageSetFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static AggregateMessageSet() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class AggregateMessageSetElement : pb::GeneratedMessage<AggregateMessageSetElement, AggregateMessageSetElement.Builder> {
    private AggregateMessageSetElement() { }
    private static readonly AggregateMessageSetElement defaultInstance = new AggregateMessageSetElement().MakeReadOnly();
    private static readonly string[] _aggregateMessageSetElementFieldNames = new string[] { "s" };
    private static readonly uint[] _aggregateMessageSetElementFieldTags = new uint[] { 10 };
    public static AggregateMessageSetElement DefaultInstance {
      get { return defaultInstance; }
    }

    public override AggregateMessageSetElement DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override AggregateMessageSetElement ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_AggregateMessageSetElement__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<AggregateMessageSetElement, AggregateMessageSetElement.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_AggregateMessageSetElement__FieldAccessorTable; }
    }

    public const int MessageSetExtensionFieldNumber = 15447542;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement> MessageSetExtension;
    public const int SFieldNumber = 1;
    private bool hasS;
    private string s_ = "";
    public bool HasS {
      get { return hasS; }
    }
    public string S {
      get { return s_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _aggregateMessageSetElementFieldNames;
      if (hasS) {
        output.WriteString(1, field_names[0], S);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasS) {
        size += pb::CodedOutputStream.ComputeStringSize(1, S);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static AggregateMessageSetElement ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static AggregateMessageSetElement ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AggregateMessageSetElement ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private AggregateMessageSetElement MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(AggregateMessageSetElement prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<AggregateMessageSetElement, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(AggregateMessageSetElement cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private AggregateMessageSetElement result;

      private AggregateMessageSetElement PrepareBuilder() {
        if (resultIsReadOnly) {
          AggregateMessageSetElement original = result;
          result = new AggregateMessageSetElement();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override AggregateMessageSetElement MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.Descriptor; }
      }

      public override AggregateMessageSetElement DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.DefaultInstance; }
      }

      public override AggregateMessageSetElement BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is AggregateMessageSetElement) {
          return MergeFrom((AggregateMessageSetElement) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(AggregateMessageSetElement other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.AggregateMessageSetElement.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasS) {
          S = other.S;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_aggregateMessageSetElementFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _aggregateMessageSetElementFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 10: {
              result.hasS = input.ReadString(ref result.s_);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasS {
        get { return result.hasS; }
      }
      public string S {
        get { return result.S; }
        set { SetS(value); }
      }
      public Builder SetS(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasS = true;
        result.s_ = value;
        return this;
      }
      public Builder ClearS() {
        PrepareBuilder();
        result.hasS = false;
        result.s_ = "";
        return this;
      }
    }
    static AggregateMessageSetElement() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Aggregate : pb::GeneratedMessage<Aggregate, Aggregate.Builder> {
    private Aggregate() { }
    private static readonly Aggregate defaultInstance = new Aggregate().MakeReadOnly();
    private static readonly string[] _aggregateFieldNames = new string[] { "file", "i", "mset", "s", "sub" };
    private static readonly uint[] _aggregateFieldTags = new uint[] { 34, 8, 42, 18, 26 };
    public static Aggregate DefaultInstance {
      get { return defaultInstance; }
    }

    public override Aggregate DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override Aggregate ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_Aggregate__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<Aggregate, Aggregate.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_Aggregate__FieldAccessorTable; }
    }

    public const int NestedFieldNumber = 15476903;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.Aggregate> Nested;
    public const int IFieldNumber = 1;
    private bool hasI;
    private int i_;
    public bool HasI {
      get { return hasI; }
    }
    public int I {
      get { return i_; }
    }

    public const int SFieldNumber = 2;
    private bool hasS;
    private string s_ = "";
    public bool HasS {
      get { return hasS; }
    }
    public string S {
      get { return s_; }
    }

    public const int SubFieldNumber = 3;
    private bool hasSub;
    private global::Google.ProtocolBuffers.TestProtos.Aggregate sub_;
    public bool HasSub {
      get { return hasSub; }
    }
    public global::Google.ProtocolBuffers.TestProtos.Aggregate Sub {
      get { return sub_ ?? global::Google.ProtocolBuffers.TestProtos.Aggregate.DefaultInstance; }
    }

    public const int FileFieldNumber = 4;
    private bool hasFile;
    private global::Google.ProtocolBuffers.DescriptorProtos.FileOptions file_;
    public bool HasFile {
      get { return hasFile; }
    }
    public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions File {
      get { return file_ ?? global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.DefaultInstance; }
    }

    public const int MsetFieldNumber = 5;
    private bool hasMset;
    private global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet mset_;
    public bool HasMset {
      get { return hasMset; }
    }
    public global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet Mset {
      get { return mset_ ?? global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.DefaultInstance; }
    }

    public override bool IsInitialized {
      get {
        if (HasSub) {
          if (!Sub.IsInitialized) return false;
        }
        if (HasFile) {
          if (!File.IsInitialized) return false;
        }
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _aggregateFieldNames;
      if (hasI) {
        output.WriteInt32(1, field_names[1], I);
      }
      if (hasS) {
        output.WriteString(2, field_names[3], S);
      }
      if (hasSub) {
        output.WriteMessage(3, field_names[4], Sub);
      }
      if (hasFile) {
        output.WriteMessage(4, field_names[0], File);
      }
      if (hasMset) {
        output.WriteMessage(5, field_names[2], Mset);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasI) {
        size += pb::CodedOutputStream.ComputeInt32Size(1, I);
      }
      if (hasS) {
        size += pb::CodedOutputStream.ComputeStringSize(2, S);
      }
      if (hasSub) {
        size += pb::CodedOutputStream.ComputeMessageSize(3, Sub);
      }
      if (hasFile) {
        size += pb::CodedOutputStream.ComputeMessageSize(4, File);
      }
      if (hasMset) {
        size += pb::CodedOutputStream.ComputeMessageSize(5, Mset);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static Aggregate ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static Aggregate ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static Aggregate ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static Aggregate ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static Aggregate ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static Aggregate ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Aggregate ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static Aggregate ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static Aggregate ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static Aggregate ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private Aggregate MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(Aggregate prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<Aggregate, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(Aggregate cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private Aggregate result;

      private Aggregate PrepareBuilder() {
        if (resultIsReadOnly) {
          Aggregate original = result;
          result = new Aggregate();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override Aggregate MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.Aggregate.Descriptor; }
      }

      public override Aggregate DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.Aggregate.DefaultInstance; }
      }

      public override Aggregate BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is Aggregate) {
          return MergeFrom((Aggregate) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(Aggregate other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.Aggregate.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasI) {
          I = other.I;
        }
        if (other.HasS) {
          S = other.S;
        }
        if (other.HasSub) {
          MergeSub(other.Sub);
        }
        if (other.HasFile) {
          MergeFile(other.File);
        }
        if (other.HasMset) {
          MergeMset(other.Mset);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_aggregateFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _aggregateFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasI = input.ReadInt32(ref result.i_);
              break;
            }
            case 18: {
              result.hasS = input.ReadString(ref result.s_);
              break;
            }
            case 26: {
              global::Google.ProtocolBuffers.TestProtos.Aggregate.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.Aggregate.CreateBuilder();
              if (result.hasSub) {
                subBuilder.MergeFrom(Sub);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              Sub = subBuilder.BuildPartial();
              break;
            }
            case 34: {
              global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.CreateBuilder();
              if (result.hasFile) {
                subBuilder.MergeFrom(File);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              File = subBuilder.BuildPartial();
              break;
            }
            case 42: {
              global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.CreateBuilder();
              if (result.hasMset) {
                subBuilder.MergeFrom(Mset);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              Mset = subBuilder.BuildPartial();
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasI {
        get { return result.hasI; }
      }
      public int I {
        get { return result.I; }
        set { SetI(value); }
      }
      public Builder SetI(int value) {
        PrepareBuilder();
        result.hasI = true;
        result.i_ = value;
        return this;
      }
      public Builder ClearI() {
        PrepareBuilder();
        result.hasI = false;
        result.i_ = 0;
        return this;
      }

      public bool HasS {
        get { return result.hasS; }
      }
      public string S {
        get { return result.S; }
        set { SetS(value); }
      }
      public Builder SetS(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasS = true;
        result.s_ = value;
        return this;
      }
      public Builder ClearS() {
        PrepareBuilder();
        result.hasS = false;
        result.s_ = "";
        return this;
      }

      public bool HasSub {
       get { return result.hasSub; }
      }
      public global::Google.ProtocolBuffers.TestProtos.Aggregate Sub {
        get { return result.Sub; }
        set { SetSub(value); }
      }
      public Builder SetSub(global::Google.ProtocolBuffers.TestProtos.Aggregate value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasSub = true;
        result.sub_ = value;
        return this;
      }
      public Builder SetSub(global::Google.ProtocolBuffers.TestProtos.Aggregate.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasSub = true;
        result.sub_ = builderForValue.Build();
        return this;
      }
      public Builder MergeSub(global::Google.ProtocolBuffers.TestProtos.Aggregate value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasSub &&
            result.sub_ != global::Google.ProtocolBuffers.TestProtos.Aggregate.DefaultInstance) {
            result.sub_ = global::Google.ProtocolBuffers.TestProtos.Aggregate.CreateBuilder(result.sub_).MergeFrom(value).BuildPartial();
        } else {
          result.sub_ = value;
        }
        result.hasSub = true;
        return this;
      }
      public Builder ClearSub() {
        PrepareBuilder();
        result.hasSub = false;
        result.sub_ = null;
        return this;
      }

      public bool HasFile {
       get { return result.hasFile; }
      }
      public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions File {
        get { return result.File; }
        set { SetFile(value); }
      }
      public Builder SetFile(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasFile = true;
        result.file_ = value;
        return this;
      }
      public Builder SetFile(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasFile = true;
        result.file_ = builderForValue.Build();
        return this;
      }
      public Builder MergeFile(global::Google.ProtocolBuffers.DescriptorProtos.FileOptions value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasFile &&
            result.file_ != global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.DefaultInstance) {
            result.file_ = global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.CreateBuilder(result.file_).MergeFrom(value).BuildPartial();
        } else {
          result.file_ = value;
        }
        result.hasFile = true;
        return this;
      }
      public Builder ClearFile() {
        PrepareBuilder();
        result.hasFile = false;
        result.file_ = null;
        return this;
      }

      public bool HasMset {
       get { return result.hasMset; }
      }
      public global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet Mset {
        get { return result.Mset; }
        set { SetMset(value); }
      }
      public Builder SetMset(global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasMset = true;
        result.mset_ = value;
        return this;
      }
      public Builder SetMset(global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasMset = true;
        result.mset_ = builderForValue.Build();
        return this;
      }
      public Builder MergeMset(global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasMset &&
            result.mset_ != global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.DefaultInstance) {
            result.mset_ = global::Google.ProtocolBuffers.TestProtos.AggregateMessageSet.CreateBuilder(result.mset_).MergeFrom(value).BuildPartial();
        } else {
          result.mset_ = value;
        }
        result.hasMset = true;
        return this;
      }
      public Builder ClearMset() {
        PrepareBuilder();
        result.hasMset = false;
        result.mset_ = null;
        return this;
      }
    }
    static Aggregate() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class AggregateMessage : pb::GeneratedMessage<AggregateMessage, AggregateMessage.Builder> {
    private AggregateMessage() { }
    private static readonly AggregateMessage defaultInstance = new AggregateMessage().MakeReadOnly();
    private static readonly string[] _aggregateMessageFieldNames = new string[] { "fieldname" };
    private static readonly uint[] _aggregateMessageFieldTags = new uint[] { 8 };
    public static AggregateMessage DefaultInstance {
      get { return defaultInstance; }
    }

    public override AggregateMessage DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override AggregateMessage ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_AggregateMessage__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<AggregateMessage, AggregateMessage.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_AggregateMessage__FieldAccessorTable; }
    }

    public const int FieldnameFieldNumber = 1;
    private bool hasFieldname;
    private int fieldname_;
    public bool HasFieldname {
      get { return hasFieldname; }
    }
    public int Fieldname {
      get { return fieldname_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _aggregateMessageFieldNames;
      if (hasFieldname) {
        output.WriteInt32(1, field_names[0], Fieldname);
      }
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      if (hasFieldname) {
        size += pb::CodedOutputStream.ComputeInt32Size(1, Fieldname);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static AggregateMessage ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AggregateMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessage ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AggregateMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessage ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AggregateMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static AggregateMessage ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static AggregateMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static AggregateMessage ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AggregateMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private AggregateMessage MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(AggregateMessage prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<AggregateMessage, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(AggregateMessage cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private AggregateMessage result;

      private AggregateMessage PrepareBuilder() {
        if (resultIsReadOnly) {
          AggregateMessage original = result;
          result = new AggregateMessage();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override AggregateMessage MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.AggregateMessage.Descriptor; }
      }

      public override AggregateMessage DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.AggregateMessage.DefaultInstance; }
      }

      public override AggregateMessage BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is AggregateMessage) {
          return MergeFrom((AggregateMessage) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(AggregateMessage other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.AggregateMessage.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasFieldname) {
          Fieldname = other.Fieldname;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_aggregateMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _aggregateMessageFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasFieldname = input.ReadInt32(ref result.fieldname_);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }


      public bool HasFieldname {
        get { return result.hasFieldname; }
      }
      public int Fieldname {
        get { return result.Fieldname; }
        set { SetFieldname(value); }
      }
      public Builder SetFieldname(int value) {
        PrepareBuilder();
        result.hasFieldname = true;
        result.fieldname_ = value;
        return this;
      }
      public Builder ClearFieldname() {
        PrepareBuilder();
        result.hasFieldname = false;
        result.fieldname_ = 0;
        return this;
      }
    }
    static AggregateMessage() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class NestedOptionType : pb::GeneratedMessage<NestedOptionType, NestedOptionType.Builder> {
    private NestedOptionType() { }
    private static readonly NestedOptionType defaultInstance = new NestedOptionType().MakeReadOnly();
    private static readonly string[] _nestedOptionTypeFieldNames = new string[] {  };
    private static readonly uint[] _nestedOptionTypeFieldTags = new uint[] {  };
    public static NestedOptionType DefaultInstance {
      get { return defaultInstance; }
    }

    public override NestedOptionType DefaultInstanceForType {
      get { return DefaultInstance; }
    }

    protected override NestedOptionType ThisMessage {
      get { return this; }
    }

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_NestedOptionType__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<NestedOptionType, NestedOptionType.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_NestedOptionType__FieldAccessorTable; }
    }

    public const int NestedExtensionFieldNumber = 7912573;
    public static pb::GeneratedExtensionBase<int> NestedExtension;
    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      public enum NestedEnum {
        NESTED_ENUM_VALUE = 1,
      }

      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class NestedMessage : pb::GeneratedMessage<NestedMessage, NestedMessage.Builder> {
        private NestedMessage() { }
        private static readonly NestedMessage defaultInstance = new NestedMessage().MakeReadOnly();
        private static readonly string[] _nestedMessageFieldNames = new string[] { "nested_field" };
        private static readonly uint[] _nestedMessageFieldTags = new uint[] { 8 };
        public static NestedMessage DefaultInstance {
          get { return defaultInstance; }
        }

        public override NestedMessage DefaultInstanceForType {
          get { return DefaultInstance; }
        }

        protected override NestedMessage ThisMessage {
          get { return this; }
        }

        public static pbd::MessageDescriptor Descriptor {
          get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_NestedOptionType_NestedMessage__Descriptor; }
        }

        protected override pb::FieldAccess.FieldAccessorTable<NestedMessage, NestedMessage.Builder> InternalFieldAccessors {
          get { return global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.internal__static_protobuf_unittest_NestedOptionType_NestedMessage__FieldAccessorTable; }
        }

        public const int NestedFieldFieldNumber = 1;
        private bool hasNestedField;
        private int nestedField_;
        public bool HasNestedField {
          get { return hasNestedField; }
        }
        public int NestedField {
          get { return nestedField_; }
        }

        public override bool IsInitialized {
          get {
            return true;
          }
        }

        public override void WriteTo(pb::ICodedOutputStream output) {
          CalcSerializedSize();
          string[] field_names = _nestedMessageFieldNames;
          if (hasNestedField) {
            output.WriteInt32(1, field_names[0], NestedField);
          }
          UnknownFields.WriteTo(output);
        }

        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            int size = memoizedSerializedSize;
            if (size != -1) return size;
            return CalcSerializedSize();
          }
        }

        private int CalcSerializedSize() {
          int size = memoizedSerializedSize;
          if (size != -1) return size;

          size = 0;
          if (hasNestedField) {
            size += pb::CodedOutputStream.ComputeInt32Size(1, NestedField);
          }
          size += UnknownFields.SerializedSize;
          memoizedSerializedSize = size;
          return size;
        }
        public static NestedMessage ParseFrom(pb::ByteString data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static NestedMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static NestedMessage ParseFrom(byte[] data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static NestedMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static NestedMessage ParseFrom(global::System.IO.Stream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static NestedMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        public static NestedMessage ParseDelimitedFrom(global::System.IO.Stream input) {
          return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
        }
        public static NestedMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
        }
        public static NestedMessage ParseFrom(pb::ICodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static NestedMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        private NestedMessage MakeReadOnly() {
          return this;
        }

        public static Builder CreateBuilder() { return new Builder(); }
        public override Builder ToBuilder() { return CreateBuilder(this); }
        public override Builder CreateBuilderForType() { return new Builder(); }
        public static Builder CreateBuilder(NestedMessage prototype) {
          return new Builder(prototype);
        }

        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public sealed partial class Builder : pb::GeneratedBuilder<NestedMessage, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {
            result = DefaultInstance;
            resultIsReadOnly = true;
          }
          internal Builder(NestedMessage cloneFrom) {
            result = cloneFrom;
            resultIsReadOnly = true;
          }

          private bool resultIsReadOnly;
          private NestedMessage result;

          private NestedMessage PrepareBuilder() {
            if (resultIsReadOnly) {
              NestedMessage original = result;
              result = new NestedMessage();
              resultIsReadOnly = false;
              MergeFrom(original);
            }
            return result;
          }

          public override bool IsInitialized {
            get { return result.IsInitialized; }
          }

          protected override NestedMessage MessageBeingBuilt {
            get { return PrepareBuilder(); }
          }

          public override Builder Clear() {
            result = DefaultInstance;
            resultIsReadOnly = true;
            return this;
          }

          public override Builder Clone() {
            if (resultIsReadOnly) {
              return new Builder(result);
            } else {
              return new Builder().MergeFrom(result);
            }
          }

          public override pbd::MessageDescriptor DescriptorForType {
            get { return global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage.Descriptor; }
          }

          public override NestedMessage DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage.DefaultInstance; }
          }

          public override NestedMessage BuildPartial() {
            if (resultIsReadOnly) {
              return result;
            }
            resultIsReadOnly = true;
            return result.MakeReadOnly();
          }

          public override Builder MergeFrom(pb::IMessage other) {
            if (other is NestedMessage) {
              return MergeFrom((NestedMessage) other);
            } else {
              base.MergeFrom(other);
              return this;
            }
          }

          public override Builder MergeFrom(NestedMessage other) {
            if (other == global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Types.NestedMessage.DefaultInstance) return this;
            PrepareBuilder();
            if (other.HasNestedField) {
              NestedField = other.NestedField;
            }
            this.MergeUnknownFields(other.UnknownFields);
            return this;
          }

          public override Builder MergeFrom(pb::ICodedInputStream input) {
            return MergeFrom(input, pb::ExtensionRegistry.Empty);
          }

          public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            PrepareBuilder();
            pb::UnknownFieldSet.Builder unknownFields = null;
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              if(tag == 0 && field_name != null) {
                int field_ordinal = global::System.Array.BinarySearch(_nestedMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
                if(field_ordinal >= 0)
                  tag = _nestedMessageFieldTags[field_ordinal];
                else {
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  continue;
                }
              }
              switch (tag) {
                case 0: {
                  throw pb::InvalidProtocolBufferException.InvalidTag();
                }
                default: {
                  if (pb::WireFormat.IsEndGroupTag(tag)) {
                    if (unknownFields != null) {
                      this.UnknownFields = unknownFields.Build();
                    }
                    return this;
                  }
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  break;
                }
                case 8: {
                  result.hasNestedField = input.ReadInt32(ref result.nestedField_);
                  break;
                }
              }
            }

            if (unknownFields != null) {
              this.UnknownFields = unknownFields.Build();
            }
            return this;
          }


          public bool HasNestedField {
            get { return result.hasNestedField; }
          }
          public int NestedField {
            get { return result.NestedField; }
            set { SetNestedField(value); }
          }
          public Builder SetNestedField(int value) {
            PrepareBuilder();
            result.hasNestedField = true;
            result.nestedField_ = value;
            return this;
          }
          public Builder ClearNestedField() {
            PrepareBuilder();
            result.hasNestedField = false;
            result.nestedField_ = 0;
            return this;
          }
        }
        static NestedMessage() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
        }
      }

    }
    #endregion

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _nestedOptionTypeFieldNames;
      UnknownFields.WriteTo(output);
    }

    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        return CalcSerializedSize();
      }
    }

    private int CalcSerializedSize() {
      int size = memoizedSerializedSize;
      if (size != -1) return size;

      size = 0;
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static NestedOptionType ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static NestedOptionType ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static NestedOptionType ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static NestedOptionType ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static NestedOptionType ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static NestedOptionType ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static NestedOptionType ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static NestedOptionType ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static NestedOptionType ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static NestedOptionType ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private NestedOptionType MakeReadOnly() {
      return this;
    }

    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(NestedOptionType prototype) {
      return new Builder(prototype);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public sealed partial class Builder : pb::GeneratedBuilder<NestedOptionType, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {
        result = DefaultInstance;
        resultIsReadOnly = true;
      }
      internal Builder(NestedOptionType cloneFrom) {
        result = cloneFrom;
        resultIsReadOnly = true;
      }

      private bool resultIsReadOnly;
      private NestedOptionType result;

      private NestedOptionType PrepareBuilder() {
        if (resultIsReadOnly) {
          NestedOptionType original = result;
          result = new NestedOptionType();
          resultIsReadOnly = false;
          MergeFrom(original);
        }
        return result;
      }

      public override bool IsInitialized {
        get { return result.IsInitialized; }
      }

      protected override NestedOptionType MessageBeingBuilt {
        get { return PrepareBuilder(); }
      }

      public override Builder Clear() {
        result = DefaultInstance;
        resultIsReadOnly = true;
        return this;
      }

      public override Builder Clone() {
        if (resultIsReadOnly) {
          return new Builder(result);
        } else {
          return new Builder().MergeFrom(result);
        }
      }

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.NestedOptionType.Descriptor; }
      }

      public override NestedOptionType DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.NestedOptionType.DefaultInstance; }
      }

      public override NestedOptionType BuildPartial() {
        if (resultIsReadOnly) {
          return result;
        }
        resultIsReadOnly = true;
        return result.MakeReadOnly();
      }

      public override Builder MergeFrom(pb::IMessage other) {
        if (other is NestedOptionType) {
          return MergeFrom((NestedOptionType) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }

      public override Builder MergeFrom(NestedOptionType other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.NestedOptionType.DefaultInstance) return this;
        PrepareBuilder();
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_nestedOptionTypeFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _nestedOptionTypeFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }

    }
    static NestedOptionType() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestCustomOptions.Descriptor, null);
    }
  }

  #endregion

}

#endregion Designer generated code
