// Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!

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()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public static partial class UnitTestXmlSerializerTestProtoFile {
  
    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionEnum);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionText);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionNumber);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionMessage);
    }
    #endregion
    #region Extensions
    public const int ExtensionEnumFieldNumber = 101;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.EnumOptions> ExtensionEnum;
    public const int ExtensionTextFieldNumber = 102;
    public static pb::GeneratedExtensionBase<string> ExtensionText;
    public const int ExtensionNumberFieldNumber = 103;
    public static pb::GeneratedExtensionBase<scg::IList<int>> ExtensionNumber;
    public const int ExtensionMessageFieldNumber = 199;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.TestXmlExtension> ExtensionMessage;
    #endregion
    
    #region Static variables
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlChild__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlChild, global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Builder> internal__static_protobuf_unittest_extra_TestXmlChild__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlNoFields__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields, global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.Builder> internal__static_protobuf_unittest_extra_TestXmlNoFields__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Builder> internal__static_protobuf_unittest_extra_TestXmlMessage__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlMessage_Children__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder> internal__static_protobuf_unittest_extra_TestXmlMessage_Children__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlExtension, global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.Builder> internal__static_protobuf_unittest_extra_TestXmlExtension__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;
    
    static UnitTestXmlSerializerTestProtoFile() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          "CiRleHRlc3QvdW5pdHRlc3RfZXh0cmFzX3htbHRlc3QucHJvdG8SF3Byb3Rv" + 
          "YnVmX3VuaXR0ZXN0X2V4dHJhGiRnb29nbGUvcHJvdG9idWYvY3NoYXJwX29w" + 
          "dGlvbnMucHJvdG8iVQoMVGVzdFhtbENoaWxkEjUKB29wdGlvbnMYAyADKA4y" + 
          "JC5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5FbnVtT3B0aW9ucxIOCgZiaW5h" + 
          "cnkYBCABKAwiEQoPVGVzdFhtbE5vRmllbGRzIrcCCg5UZXN0WG1sTWVzc2Fn" + 
          "ZRIOCgZudW1iZXIYBiABKAMSDwoHbnVtYmVycxgCIAMoBRIMCgR0ZXh0GAMg" + 
          "ASgJEhIKCXRleHRsaW5lcxi8BSADKAkSDQoFdmFsaWQYBSABKAgSNAoFY2hp" + 
          "bGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1sQ2hp" + 
          "bGQSQwoIY2hpbGRyZW4YkQMgAygKMjAucHJvdG9idWZfdW5pdHRlc3RfZXh0" + 
          "cmEuVGVzdFhtbE1lc3NhZ2UuQ2hpbGRyZW4aUQoIQ2hpbGRyZW4SNQoHb3B0" + 
          "aW9ucxgDIAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2V4dHJhLkVudW1PcHRp" + 
          "b25zEg4KBmJpbmFyeRgEIAEoDCoFCGQQyAEiIgoQVGVzdFhtbEV4dGVuc2lv" + 
          "bhIOCgZudW1iZXIYASACKAUqKgoLRW51bU9wdGlvbnMSBwoDT05FEAASBwoD" + 
          "VFdPEAESCQoFVEhSRUUQAjplCg5leHRlbnNpb25fZW51bRInLnByb3RvYnVm" + 
          "X3VuaXR0ZXN0X2V4dHJhLlRlc3RYbWxNZXNzYWdlGGUgASgOMiQucHJvdG9i" + 
          "dWZfdW5pdHRlc3RfZXh0cmEuRW51bU9wdGlvbnM6PwoOZXh0ZW5zaW9uX3Rl" + 
          "eHQSJy5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1sTWVzc2FnZRhm" + 
          "IAEoCTpFChBleHRlbnNpb25fbnVtYmVyEicucHJvdG9idWZfdW5pdHRlc3Rf" + 
          "ZXh0cmEuVGVzdFhtbE1lc3NhZ2UYZyADKAVCAhABOm4KEWV4dGVuc2lvbl9t" + 
          "ZXNzYWdlEicucHJvdG9idWZfdW5pdHRlc3RfZXh0cmEuVGVzdFhtbE1lc3Nh" + 
          "Z2UYxwEgASgLMikucHJvdG9idWZfdW5pdHRlc3RfZXh0cmEuVGVzdFhtbEV4" + 
          "dGVuc2lvbkJMSAHCPkcKIUdvb2dsZS5Qcm90b2NvbEJ1ZmZlcnMuVGVzdFBy" + 
          "b3RvcxIiVW5pdFRlc3RYbWxTZXJpYWxpemVyVGVzdFByb3RvRmlsZQ==");
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_protobuf_unittest_extra_TestXmlChild__Descriptor = Descriptor.MessageTypes[0];
        internal__static_protobuf_unittest_extra_TestXmlChild__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlChild, global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Builder>(internal__static_protobuf_unittest_extra_TestXmlChild__Descriptor,
                new string[] { "Options", "Binary", });
        internal__static_protobuf_unittest_extra_TestXmlNoFields__Descriptor = Descriptor.MessageTypes[1];
        internal__static_protobuf_unittest_extra_TestXmlNoFields__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields, global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.Builder>(internal__static_protobuf_unittest_extra_TestXmlNoFields__Descriptor,
                new string[] { });
        internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor = Descriptor.MessageTypes[2];
        internal__static_protobuf_unittest_extra_TestXmlMessage__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Builder>(internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor,
                new string[] { "Number", "Numbers", "Text", "Textlines", "Valid", "Child", "Children", });
        internal__static_protobuf_unittest_extra_TestXmlMessage_Children__Descriptor = internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor.NestedTypes[0];
        internal__static_protobuf_unittest_extra_TestXmlMessage_Children__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder>(internal__static_protobuf_unittest_extra_TestXmlMessage_Children__Descriptor,
                new string[] { "Options", "Binary", });
        internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor = Descriptor.MessageTypes[3];
        internal__static_protobuf_unittest_extra_TestXmlExtension__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlExtension, global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.Builder>(internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor,
                new string[] { "Number", });
        global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionEnum = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.EnumOptions>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor.Extensions[0]);
        global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionText = pb::GeneratedSingleExtension<string>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor.Extensions[1]);
        global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionNumber = pb::GeneratedRepeatExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor.Extensions[2]);
        global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.ExtensionMessage = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.TestXmlExtension>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor.Extensions[3]);
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor, 
          }, assigner);
    }
    #endregion
    
  }
  #region Enums
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public enum EnumOptions {
    ONE = 0,
    TWO = 1,
    THREE = 2,
  }
  
  #endregion
  
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class TestXmlChild : pb::GeneratedMessage<TestXmlChild, TestXmlChild.Builder> {
    private static readonly TestXmlChild defaultInstance = new Builder().BuildPartial();
    public static TestXmlChild DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestXmlChild DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestXmlChild ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlChild__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<TestXmlChild, TestXmlChild.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlChild__FieldAccessorTable; }
    }
    
    public const int OptionsFieldNumber = 3;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> options_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> OptionsList {
      get { return pbc::Lists.AsReadOnly(options_); }
    }
    public int OptionsCount {
      get { return options_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.EnumOptions GetOptions(int index) {
      return options_[index];
    }
    
    public const int BinaryFieldNumber = 4;
    private bool hasBinary;
    private pb::ByteString binary_ = pb::ByteString.Empty;
    public bool HasBinary {
      get { return hasBinary; }
    }
    public pb::ByteString Binary {
      get { return binary_; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      if (options_.Count > 0) {
        output.WriteArray(pbd::FieldType.Enum, 3, "options", options_);
      }
      if (HasBinary) {
        output.WriteBytes(4, "binary", Binary);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        {
          int dataSize = 0;
          if (options_.Count > 0) {
            foreach (global::Google.ProtocolBuffers.TestProtos.EnumOptions element in options_) {
              dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
            }
            size += dataSize;
            size += 1 * options_.Count;
          }
        }
        if (HasBinary) {
          size += pb::CodedOutputStream.ComputeBytesSize(4, Binary);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static TestXmlChild ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlChild ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlChild ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlChild ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlChild ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlChild ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestXmlChild ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestXmlChild ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestXmlChild ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlChild ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(TestXmlChild prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<TestXmlChild, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestXmlChild result = new TestXmlChild();
      
      protected override TestXmlChild MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestXmlChild();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Descriptor; }
      }
      
      public override TestXmlChild DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance; }
      }
      
      public override TestXmlChild BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.options_.MakeReadOnly();
        TestXmlChild returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is TestXmlChild) {
          return MergeFrom((TestXmlChild) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestXmlChild other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance) return this;
        if (other.options_.Count != 0) {
          base.AddRange(other.options_, result.options_);
        }
        if (other.HasBinary) {
          Binary = other.Binary;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        while (true) {
          uint tag = input.ReadTag();
          switch (tag) {
            case 0: {
              if (unknownFields != null) {
                this.UnknownFields = unknownFields.Build();
              }
              return this;
            }
            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);
              break;
            }
            case 24: {
              int rawValue = input.ReadEnum();
              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.EnumOptions), rawValue)) {
                if (unknownFields == null) {
                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                }
                unknownFields.MergeVarintField(3, (ulong) rawValue);
              } else {
                AddOptions((global::Google.ProtocolBuffers.TestProtos.EnumOptions) rawValue);
              }
              break;
            }
            case 34: {
              Binary = input.ReadBytes();
              break;
            }
          }
        }
      }
      
      
      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> OptionsList {
        get { return result.options_; }
      }
      public int OptionsCount {
        get { return result.OptionsCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.EnumOptions GetOptions(int index) {
        return result.GetOptions(index);
      }
      public Builder SetOptions(int index, global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
        result.options_[index] = value;
        return this;
      }
      public Builder AddOptions(global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
        result.options_.Add(value);
        return this;
      }
      public Builder AddRangeOptions(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.EnumOptions> values) {
        base.AddRange(values, result.options_);
        return this;
      }
      public Builder ClearOptions() {
        result.options_.Clear();
        return this;
      }
      
      public bool HasBinary {
        get { return result.HasBinary; }
      }
      public pb::ByteString Binary {
        get { return result.Binary; }
        set { SetBinary(value); }
      }
      public Builder SetBinary(pb::ByteString value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.hasBinary = true;
        result.binary_ = value;
        return this;
      }
      public Builder ClearBinary() {
        result.hasBinary = false;
        result.binary_ = pb::ByteString.Empty;
        return this;
      }
    }
    static TestXmlChild() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class TestXmlNoFields : pb::GeneratedMessage<TestXmlNoFields, TestXmlNoFields.Builder> {
    private static readonly TestXmlNoFields defaultInstance = new Builder().BuildPartial();
    public static TestXmlNoFields DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestXmlNoFields DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestXmlNoFields ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlNoFields__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<TestXmlNoFields, TestXmlNoFields.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlNoFields__FieldAccessorTable; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static TestXmlNoFields ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestXmlNoFields ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestXmlNoFields ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlNoFields ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(TestXmlNoFields prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<TestXmlNoFields, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestXmlNoFields result = new TestXmlNoFields();
      
      protected override TestXmlNoFields MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestXmlNoFields();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.Descriptor; }
      }
      
      public override TestXmlNoFields DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.DefaultInstance; }
      }
      
      public override TestXmlNoFields BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        TestXmlNoFields returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is TestXmlNoFields) {
          return MergeFrom((TestXmlNoFields) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestXmlNoFields other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.DefaultInstance) return this;
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        while (true) {
          uint tag = input.ReadTag();
          switch (tag) {
            case 0: {
              if (unknownFields != null) {
                this.UnknownFields = unknownFields.Build();
              }
              return this;
            }
            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);
              break;
            }
          }
        }
      }
      
    }
    static TestXmlNoFields() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class TestXmlMessage : pb::ExtendableMessage<TestXmlMessage, TestXmlMessage.Builder> {
    private static readonly TestXmlMessage defaultInstance = new Builder().BuildPartial();
    public static TestXmlMessage DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestXmlMessage DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestXmlMessage ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<TestXmlMessage, TestXmlMessage.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlMessage__FieldAccessorTable; }
    }
    
    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public static class Types {
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
      [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
      public sealed partial class Children : pb::GeneratedMessage<Children, Children.Builder> {
        private static readonly Children defaultInstance = new Builder().BuildPartial();
        public static Children DefaultInstance {
          get { return defaultInstance; }
        }
        
        public override Children DefaultInstanceForType {
          get { return defaultInstance; }
        }
        
        protected override Children ThisMessage {
          get { return this; }
        }
        
        public static pbd::MessageDescriptor Descriptor {
          get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlMessage_Children__Descriptor; }
        }
        
        protected override pb::FieldAccess.FieldAccessorTable<Children, Children.Builder> InternalFieldAccessors {
          get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlMessage_Children__FieldAccessorTable; }
        }
        
        public const int OptionsFieldNumber = 3;
        private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> options_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions>();
        public scg::IList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> OptionsList {
          get { return pbc::Lists.AsReadOnly(options_); }
        }
        public int OptionsCount {
          get { return options_.Count; }
        }
        public global::Google.ProtocolBuffers.TestProtos.EnumOptions GetOptions(int index) {
          return options_[index];
        }
        
        public const int BinaryFieldNumber = 4;
        private bool hasBinary;
        private pb::ByteString binary_ = pb::ByteString.Empty;
        public bool HasBinary {
          get { return hasBinary; }
        }
        public pb::ByteString Binary {
          get { return binary_; }
        }
        
        public override bool IsInitialized {
          get {
            return true;
          }
        }
        
        public override void WriteTo(pb::ICodedOutputStream output) {
          int size = SerializedSize;
          if (options_.Count > 0) {
            output.WriteArray(pbd::FieldType.Enum, 3, "options", options_);
          }
          if (HasBinary) {
            output.WriteBytes(4, "binary", Binary);
          }
          UnknownFields.WriteTo(output);
        }
        
        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            int size = memoizedSerializedSize;
            if (size != -1) return size;
            
            size = 0;
            {
              int dataSize = 0;
              if (options_.Count > 0) {
                foreach (global::Google.ProtocolBuffers.TestProtos.EnumOptions element in options_) {
                  dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
                }
                size += dataSize;
                size += 1 * options_.Count;
              }
            }
            if (HasBinary) {
              size += pb::CodedOutputStream.ComputeBytesSize(4, Binary);
            }
            size += UnknownFields.SerializedSize;
            memoizedSerializedSize = size;
            return size;
          }
        }
        
        public static Children ParseFrom(pb::ByteString data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static Children ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static Children ParseFrom(byte[] data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static Children ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static Children ParseFrom(global::System.IO.Stream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static Children ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        public static Children ParseDelimitedFrom(global::System.IO.Stream input) {
          return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
        }
        public static Children ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
        }
        public static Children ParseFrom(pb::CodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static Children ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        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(Children prototype) {
          return (Builder) new Builder().MergeFrom(prototype);
        }
        
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
        public sealed partial class Builder : pb::GeneratedBuilder<Children, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {}
          
          Children result = new Children();
          
          protected override Children MessageBeingBuilt {
            get { return result; }
          }
          
          public override Builder Clear() {
            result = new Children();
            return this;
          }
          
          public override Builder Clone() {
            return new Builder().MergeFrom(result);
          }
          
          public override pbd::MessageDescriptor DescriptorForType {
            get { return global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Descriptor; }
          }
          
          public override Children DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.DefaultInstance; }
          }
          
          public override Children BuildPartial() {
            if (result == null) {
              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
            }
            result.options_.MakeReadOnly();
            Children returnMe = result;
            result = null;
            return returnMe;
          }
          
          public override Builder MergeFrom(pb::IMessage other) {
            if (other is Children) {
              return MergeFrom((Children) other);
            } else {
              base.MergeFrom(other);
              return this;
            }
          }
          
          public override Builder MergeFrom(Children other) {
            if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.DefaultInstance) return this;
            if (other.options_.Count != 0) {
              base.AddRange(other.options_, result.options_);
            }
            if (other.HasBinary) {
              Binary = other.Binary;
            }
            this.MergeUnknownFields(other.UnknownFields);
            return this;
          }
          
          public override Builder MergeFrom(pb::CodedInputStream input) {
            return MergeFrom(input, pb::ExtensionRegistry.Empty);
          }
          
          public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            pb::UnknownFieldSet.Builder unknownFields = null;
            while (true) {
              uint tag = input.ReadTag();
              switch (tag) {
                case 0: {
                  if (unknownFields != null) {
                    this.UnknownFields = unknownFields.Build();
                  }
                  return this;
                }
                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);
                  break;
                }
                case 24: {
                  int rawValue = input.ReadEnum();
                  if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.EnumOptions), rawValue)) {
                    if (unknownFields == null) {
                      unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                    }
                    unknownFields.MergeVarintField(3, (ulong) rawValue);
                  } else {
                    AddOptions((global::Google.ProtocolBuffers.TestProtos.EnumOptions) rawValue);
                  }
                  break;
                }
                case 34: {
                  Binary = input.ReadBytes();
                  break;
                }
              }
            }
          }
          
          
          public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.EnumOptions> OptionsList {
            get { return result.options_; }
          }
          public int OptionsCount {
            get { return result.OptionsCount; }
          }
          public global::Google.ProtocolBuffers.TestProtos.EnumOptions GetOptions(int index) {
            return result.GetOptions(index);
          }
          public Builder SetOptions(int index, global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
            result.options_[index] = value;
            return this;
          }
          public Builder AddOptions(global::Google.ProtocolBuffers.TestProtos.EnumOptions value) {
            result.options_.Add(value);
            return this;
          }
          public Builder AddRangeOptions(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.EnumOptions> values) {
            base.AddRange(values, result.options_);
            return this;
          }
          public Builder ClearOptions() {
            result.options_.Clear();
            return this;
          }
          
          public bool HasBinary {
            get { return result.HasBinary; }
          }
          public pb::ByteString Binary {
            get { return result.Binary; }
            set { SetBinary(value); }
          }
          public Builder SetBinary(pb::ByteString value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasBinary = true;
            result.binary_ = value;
            return this;
          }
          public Builder ClearBinary() {
            result.hasBinary = false;
            result.binary_ = pb::ByteString.Empty;
            return this;
          }
        }
        static Children() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor, null);
        }
      }
      
    }
    #endregion
    
    public const int NumberFieldNumber = 6;
    private bool hasNumber;
    private long number_ = 0L;
    public bool HasNumber {
      get { return hasNumber; }
    }
    public long Number {
      get { return number_; }
    }
    
    public const int NumbersFieldNumber = 2;
    private pbc::PopsicleList<int> numbers_ = new pbc::PopsicleList<int>();
    public scg::IList<int> NumbersList {
      get { return pbc::Lists.AsReadOnly(numbers_); }
    }
    public int NumbersCount {
      get { return numbers_.Count; }
    }
    public int GetNumbers(int index) {
      return numbers_[index];
    }
    
    public const int TextFieldNumber = 3;
    private bool hasText;
    private string text_ = "";
    public bool HasText {
      get { return hasText; }
    }
    public string Text {
      get { return text_; }
    }
    
    public const int TextlinesFieldNumber = 700;
    private pbc::PopsicleList<string> textlines_ = new pbc::PopsicleList<string>();
    public scg::IList<string> TextlinesList {
      get { return pbc::Lists.AsReadOnly(textlines_); }
    }
    public int TextlinesCount {
      get { return textlines_.Count; }
    }
    public string GetTextlines(int index) {
      return textlines_[index];
    }
    
    public const int ValidFieldNumber = 5;
    private bool hasValid;
    private bool valid_ = false;
    public bool HasValid {
      get { return hasValid; }
    }
    public bool Valid {
      get { return valid_; }
    }
    
    public const int ChildFieldNumber = 1;
    private bool hasChild;
    private global::Google.ProtocolBuffers.TestProtos.TestXmlChild child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance;
    public bool HasChild {
      get { return hasChild; }
    }
    public global::Google.ProtocolBuffers.TestProtos.TestXmlChild Child {
      get { return child_; }
    }
    
    public const int ChildrenFieldNumber = 401;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children> children_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children> ChildrenList {
      get { return children_; }
    }
    public int ChildrenCount {
      get { return children_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children GetChildren(int index) {
      return children_[index];
    }
    
    public override bool IsInitialized {
      get {
        if (!ExtensionsAreInitialized) return false;
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      pb::ExtendableMessage<TestXmlMessage, TestXmlMessage.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      if (HasChild) {
        output.WriteMessage(1, "child", Child);
      }
      if (numbers_.Count > 0) {
        output.WriteArray(pbd::FieldType.Int32, 2, "numbers", numbers_);
      }
      if (HasText) {
        output.WriteString(3, "text", Text);
      }
      if (HasValid) {
        output.WriteBool(5, "valid", Valid);
      }
      if (HasNumber) {
        output.WriteInt64(6, "number", Number);
      }
      extensionWriter.WriteUntil(200, output);
      if (children_.Count > 0) {
        output.WriteArray(pbd::FieldType.Group, 401, "children", children_);
      }
      if (textlines_.Count > 0) {
        output.WriteArray(pbd::FieldType.String, 700, "textlines", textlines_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (HasNumber) {
          size += pb::CodedOutputStream.ComputeInt64Size(6, Number);
        }
        {
          int dataSize = 0;
          foreach (int element in NumbersList) {
            dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
          }
          size += dataSize;
          size += 1 * numbers_.Count;
        }
        if (HasText) {
          size += pb::CodedOutputStream.ComputeStringSize(3, Text);
        }
        {
          int dataSize = 0;
          foreach (string element in TextlinesList) {
            dataSize += pb::CodedOutputStream.ComputeStringSizeNoTag(element);
          }
          size += dataSize;
          size += 2 * textlines_.Count;
        }
        if (HasValid) {
          size += pb::CodedOutputStream.ComputeBoolSize(5, Valid);
        }
        if (HasChild) {
          size += pb::CodedOutputStream.ComputeMessageSize(1, Child);
        }
        foreach (global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children element in ChildrenList) {
          size += pb::CodedOutputStream.ComputeGroupSize(401, element);
        }
        size += ExtensionsSerializedSize;
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static TestXmlMessage ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestXmlMessage ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestXmlMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlMessage ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(TestXmlMessage prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::ExtendableBuilder<TestXmlMessage, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestXmlMessage result = new TestXmlMessage();
      
      protected override TestXmlMessage MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestXmlMessage();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Descriptor; }
      }
      
      public override TestXmlMessage DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.DefaultInstance; }
      }
      
      public override TestXmlMessage BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.numbers_.MakeReadOnly();
        result.textlines_.MakeReadOnly();
        result.children_.MakeReadOnly();
        TestXmlMessage returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is TestXmlMessage) {
          return MergeFrom((TestXmlMessage) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestXmlMessage other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.DefaultInstance) return this;
        if (other.HasNumber) {
          Number = other.Number;
        }
        if (other.numbers_.Count != 0) {
          base.AddRange(other.numbers_, result.numbers_);
        }
        if (other.HasText) {
          Text = other.Text;
        }
        if (other.textlines_.Count != 0) {
          base.AddRange(other.textlines_, result.textlines_);
        }
        if (other.HasValid) {
          Valid = other.Valid;
        }
        if (other.HasChild) {
          MergeChild(other.Child);
        }
        if (other.children_.Count != 0) {
          base.AddRange(other.children_, result.children_);
        }
          this.MergeExtensionFields(other);
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        while (true) {
          uint tag = input.ReadTag();
          switch (tag) {
            case 0: {
              if (unknownFields != null) {
                this.UnknownFields = unknownFields.Build();
              }
              return this;
            }
            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);
              break;
            }
            case 10: {
              global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.CreateBuilder();
              if (HasChild) {
                subBuilder.MergeFrom(Child);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              Child = subBuilder.BuildPartial();
              break;
            }
            case 16: {
              AddNumbers(input.ReadInt32());
              break;
            }
            case 26: {
              Text = input.ReadString();
              break;
            }
            case 40: {
              Valid = input.ReadBool();
              break;
            }
            case 48: {
              Number = input.ReadInt64();
              break;
            }
            case 3211: {
              global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.CreateBuilder();
              input.ReadGroup(401, subBuilder, extensionRegistry);
              AddChildren(subBuilder.BuildPartial());
              break;
            }
            case 5602: {
              AddTextlines(input.ReadString());
              break;
            }
          }
        }
      }
      
      
      public bool HasNumber {
        get { return result.HasNumber; }
      }
      public long Number {
        get { return result.Number; }
        set { SetNumber(value); }
      }
      public Builder SetNumber(long value) {
        result.hasNumber = true;
        result.number_ = value;
        return this;
      }
      public Builder ClearNumber() {
        result.hasNumber = false;
        result.number_ = 0L;
        return this;
      }
      
      public pbc::IPopsicleList<int> NumbersList {
        get { return result.numbers_; }
      }
      public int NumbersCount {
        get { return result.NumbersCount; }
      }
      public int GetNumbers(int index) {
        return result.GetNumbers(index);
      }
      public Builder SetNumbers(int index, int value) {
        result.numbers_[index] = value;
        return this;
      }
      public Builder AddNumbers(int value) {
        result.numbers_.Add(value);
        return this;
      }
      public Builder AddRangeNumbers(scg::IEnumerable<int> values) {
        base.AddRange(values, result.numbers_);
        return this;
      }
      public Builder ClearNumbers() {
        result.numbers_.Clear();
        return this;
      }
      
      public bool HasText {
        get { return result.HasText; }
      }
      public string Text {
        get { return result.Text; }
        set { SetText(value); }
      }
      public Builder SetText(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.hasText = true;
        result.text_ = value;
        return this;
      }
      public Builder ClearText() {
        result.hasText = false;
        result.text_ = "";
        return this;
      }
      
      public pbc::IPopsicleList<string> TextlinesList {
        get { return result.textlines_; }
      }
      public int TextlinesCount {
        get { return result.TextlinesCount; }
      }
      public string GetTextlines(int index) {
        return result.GetTextlines(index);
      }
      public Builder SetTextlines(int index, string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.textlines_[index] = value;
        return this;
      }
      public Builder AddTextlines(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.textlines_.Add(value);
        return this;
      }
      public Builder AddRangeTextlines(scg::IEnumerable<string> values) {
        base.AddRange(values, result.textlines_);
        return this;
      }
      public Builder ClearTextlines() {
        result.textlines_.Clear();
        return this;
      }
      
      public bool HasValid {
        get { return result.HasValid; }
      }
      public bool Valid {
        get { return result.Valid; }
        set { SetValid(value); }
      }
      public Builder SetValid(bool value) {
        result.hasValid = true;
        result.valid_ = value;
        return this;
      }
      public Builder ClearValid() {
        result.hasValid = false;
        result.valid_ = false;
        return this;
      }
      
      public bool HasChild {
       get { return result.HasChild; }
      }
      public global::Google.ProtocolBuffers.TestProtos.TestXmlChild Child {
        get { return result.Child; }
        set { SetChild(value); }
      }
      public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlChild value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.hasChild = true;
        result.child_ = value;
        return this;
      }
      public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.hasChild = true;
        result.child_ = builderForValue.Build();
        return this;
      }
      public Builder MergeChild(global::Google.ProtocolBuffers.TestProtos.TestXmlChild value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        if (result.HasChild &&
            result.child_ != global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance) {
            result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.CreateBuilder(result.child_).MergeFrom(value).BuildPartial();
        } else {
          result.child_ = value;
        }
        result.hasChild = true;
        return this;
      }
      public Builder ClearChild() {
        result.hasChild = false;
        result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.DefaultInstance;
        return this;
      }
      
      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children> ChildrenList {
        get { return result.children_; }
      }
      public int ChildrenCount {
        get { return result.ChildrenCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children GetChildren(int index) {
        return result.GetChildren(index);
      }
      public Builder SetChildren(int index, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.children_[index] = value;
        return this;
      }
      public Builder SetChildren(int index, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.children_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddChildren(global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.children_.Add(value);
        return this;
      }
      public Builder AddChildren(global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.children_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangeChildren(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children> values) {
        base.AddRange(values, result.children_);
        return this;
      }
      public Builder ClearChildren() {
        result.children_.Clear();
        return this;
      }
    }
    static TestXmlMessage() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class TestXmlExtension : pb::GeneratedMessage<TestXmlExtension, TestXmlExtension.Builder> {
    private static readonly TestXmlExtension defaultInstance = new Builder().BuildPartial();
    public static TestXmlExtension DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestXmlExtension DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestXmlExtension ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<TestXmlExtension, TestXmlExtension.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlExtension__FieldAccessorTable; }
    }
    
    public const int NumberFieldNumber = 1;
    private bool hasNumber;
    private int number_ = 0;
    public bool HasNumber {
      get { return hasNumber; }
    }
    public int Number {
      get { return number_; }
    }
    
    public override bool IsInitialized {
      get {
        if (!hasNumber) return false;
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      if (HasNumber) {
        output.WriteInt32(1, "number", Number);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (HasNumber) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, Number);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static TestXmlExtension ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestXmlExtension ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestXmlExtension ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestXmlExtension ParseFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    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(TestXmlExtension prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<TestXmlExtension, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestXmlExtension result = new TestXmlExtension();
      
      protected override TestXmlExtension MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestXmlExtension();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.Descriptor; }
      }
      
      public override TestXmlExtension DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.DefaultInstance; }
      }
      
      public override TestXmlExtension BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        TestXmlExtension returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is TestXmlExtension) {
          return MergeFrom((TestXmlExtension) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestXmlExtension other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.DefaultInstance) return this;
        if (other.HasNumber) {
          Number = other.Number;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        while (true) {
          uint tag = input.ReadTag();
          switch (tag) {
            case 0: {
              if (unknownFields != null) {
                this.UnknownFields = unknownFields.Build();
              }
              return this;
            }
            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);
              break;
            }
            case 8: {
              Number = input.ReadInt32();
              break;
            }
          }
        }
      }
      
      
      public bool HasNumber {
        get { return result.HasNumber; }
      }
      public int Number {
        get { return result.Number; }
        set { SetNumber(value); }
      }
      public Builder SetNumber(int value) {
        result.hasNumber = true;
        result.number_ = value;
        return this;
      }
      public Builder ClearNumber() {
        result.hasNumber = false;
        result.number_ = 0;
        return this;
      }
    }
    static TestXmlExtension() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor, null);
    }
  }
  
  #endregion
  
}
