// 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;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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: {
              scg::ICollection<object> unknownItems;
              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.EnumOptions>(tag, field_name, result.options_, out unknownItems);
              if (unknownItems != null) {
                if (unknownFields == null) {
                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                }
                foreach (object rawValue in unknownItems)
                  if (rawValue is int)
                    unknownFields.MergeVarintField(3, (ulong)(int)rawValue);
              }
              break;
            }
            case 34: {
              result.hasBinary |= input.ReadBytes(ref result.binary_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      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;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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 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;
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              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: {
                  scg::ICollection<object> unknownItems;
                  input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.EnumOptions>(tag, field_name, result.options_, out unknownItems);
                  if (unknownItems != null) {
                    if (unknownFields == null) {
                      unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                    }
                    foreach (object rawValue in unknownItems)
                      if (rawValue is int)
                        unknownFields.MergeVarintField(3, (ulong)(int)rawValue);
                  }
                  break;
                }
                case 34: {
                  result.hasBinary |= input.ReadBytes(ref result.binary_);
                  break;
                }
              }
            }
            
            if (unknownFields != null) {
              this.UnknownFields = unknownFields.Build();
            }
            return this;
          }
          
          
          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;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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.TestXmlChild.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestXmlChild.CreateBuilder();
              if (HasChild) {
                subBuilder.MergeFrom(Child);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              Child = subBuilder.BuildPartial();
              break;
            }
            case 16: {
              input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.numbers_);
              break;
            }
            case 26: {
              result.hasText |= input.ReadString(ref result.text_);
              break;
            }
            case 40: {
              result.hasValid |= input.ReadBool(ref result.valid_);
              break;
            }
            case 48: {
              result.hasNumber |= input.ReadInt64(ref result.number_);
              break;
            }
            case 3211: {
              input.ReadGroupArray(tag, field_name, result.children_, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.DefaultInstance, extensionRegistry);
              break;
            }
            case 5602: {
              input.ReadPrimitiveArray(pbd::FieldType.String, tag, field_name, result.textlines_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      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;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          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.hasNumber |= input.ReadInt32(ref result.number_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      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
  
}
