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

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

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

    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
    }
    #endregion
    #region Static variables
    internal static pbd::MessageDescriptor internal__static_tutorial_Person__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.Examples.AddressBook.Person, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder> internal__static_tutorial_Person__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_tutorial_Person_PhoneNumber__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder> internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_tutorial_AddressBook__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook, global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook.Builder> internal__static_tutorial_AddressBook__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;

    static Addressbook() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi2gEKBlBlcnNvbhIMCgRu", 
            "YW1lGAEgAigJEgoKAmlkGAIgAigFEg0KBWVtYWlsGAMgASgJEisKBXBob25l", 
            "GAQgAygLMhwudHV0b3JpYWwuUGVyc29uLlBob25lTnVtYmVyGk0KC1Bob25l", 
            "TnVtYmVyEg4KBm51bWJlchgBIAIoCRIuCgR0eXBlGAIgASgOMhoudHV0b3Jp", 
            "YWwuUGVyc29uLlBob25lVHlwZToESE9NRSIrCglQaG9uZVR5cGUSCgoGTU9C", 
            "SUxFEAASCAoESE9NRRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZw", 
            "ZXJzb24YASADKAsyEC50dXRvcmlhbC5QZXJzb25CVwoUY29tLmV4YW1wbGUu", 
            "dHV0b3JpYWxCEUFkZHJlc3NCb29rUHJvdG9zqgIrR29vZ2xlLlByb3RvY29s", 
          "QnVmZmVycy5FeGFtcGxlcy5BZGRyZXNzQm9vaw=="));
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_tutorial_Person__Descriptor = Descriptor.MessageTypes[0];
        internal__static_tutorial_Person__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.Examples.AddressBook.Person, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder>(internal__static_tutorial_Person__Descriptor,
                new string[] { "Name", "Id", "Email", "Phone", });
        internal__static_tutorial_Person_PhoneNumber__Descriptor = internal__static_tutorial_Person__Descriptor.NestedTypes[0];
        internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder>(internal__static_tutorial_Person_PhoneNumber__Descriptor,
                new string[] { "Number", "Type", });
        internal__static_tutorial_AddressBook__Descriptor = Descriptor.MessageTypes[1];
        internal__static_tutorial_AddressBook__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook, global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook.Builder>(internal__static_tutorial_AddressBook__Descriptor,
                new string[] { "Person", });
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          }, assigner);
    }
    #endregion

  }
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class Person : pb::GeneratedMessage<Person, Person.Builder> {
    private Person() { }
    private static readonly Person defaultInstance = new Person().MakeReadOnly();
    private static readonly string[] _personFieldNames = new string[] { "email", "id", "name", "phone" };
    private static readonly uint[] _personFieldTags = new uint[] { 26, 16, 10, 34 };
    public static Person DefaultInstance {
      get { return defaultInstance; }
    }

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

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

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_Person__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<Person, Person.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_Person__FieldAccessorTable; }
    }

    #region Nested types
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public static partial class Types {
      public enum PhoneType {
        MOBILE = 0,
        HOME = 1,
        WORK = 2,
      }

      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class PhoneNumber : pb::GeneratedMessage<PhoneNumber, PhoneNumber.Builder> {
        private PhoneNumber() { }
        private static readonly PhoneNumber defaultInstance = new PhoneNumber().MakeReadOnly();
        private static readonly string[] _phoneNumberFieldNames = new string[] { "number", "type" };
        private static readonly uint[] _phoneNumberFieldTags = new uint[] { 10, 16 };
        public static PhoneNumber DefaultInstance {
          get { return defaultInstance; }
        }

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

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

        public static pbd::MessageDescriptor Descriptor {
          get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_Person_PhoneNumber__Descriptor; }
        }

        protected override pb::FieldAccess.FieldAccessorTable<PhoneNumber, PhoneNumber.Builder> InternalFieldAccessors {
          get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_Person_PhoneNumber__FieldAccessorTable; }
        }

        public const int NumberFieldNumber = 1;
        private bool hasNumber;
        private string number_ = "";
        public bool HasNumber {
          get { return hasNumber; }
        }
        public string Number {
          get { return number_; }
        }

        public const int TypeFieldNumber = 2;
        private bool hasType;
        private global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType type_ = global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME;
        public bool HasType {
          get { return hasType; }
        }
        public global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType Type {
          get { return type_; }
        }

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

        public override void WriteTo(pb::ICodedOutputStream output) {
          CalcSerializedSize();
          string[] field_names = _phoneNumberFieldNames;
          if (hasNumber) {
            output.WriteString(1, field_names[0], Number);
          }
          if (hasType) {
            output.WriteEnum(2, field_names[1], (int) Type, Type);
          }
          UnknownFields.WriteTo(output);
        }

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

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

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

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

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

          private bool resultIsReadOnly;
          private PhoneNumber result;

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

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

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

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

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

          public override pbd::MessageDescriptor DescriptorForType {
            get { return global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Descriptor; }
          }

          public override PhoneNumber DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.DefaultInstance; }
          }

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

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

          public override Builder MergeFrom(PhoneNumber other) {
            if (other == global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.DefaultInstance) return this;
            PrepareBuilder();
            if (other.HasNumber) {
              Number = other.Number;
            }
            if (other.HasType) {
              Type = other.Type;
            }
            this.MergeUnknownFields(other.UnknownFields);
            return this;
          }

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

          public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            PrepareBuilder();
            pb::UnknownFieldSet.Builder unknownFields = null;
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              if(tag == 0 && field_name != null) {
                int field_ordinal = global::System.Array.BinarySearch(_phoneNumberFieldNames, field_name, global::System.StringComparer.Ordinal);
                if(field_ordinal >= 0)
                  tag = _phoneNumberFieldTags[field_ordinal];
                else {
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  continue;
                }
              }
              switch (tag) {
                case 0: {
                  throw pb::InvalidProtocolBufferException.InvalidTag();
                }
                default: {
                  if (pb::WireFormat.IsEndGroupTag(tag)) {
                    if (unknownFields != null) {
                      this.UnknownFields = unknownFields.Build();
                    }
                    return this;
                  }
                  if (unknownFields == null) {
                    unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                  }
                  ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
                  break;
                }
                case 10: {
                  result.hasNumber = input.ReadString(ref result.number_);
                  break;
                }
                case 16: {
                  object unknown;
                  if(input.ReadEnum(ref result.type_, out unknown)) {
                    result.hasType = true;
                  } else if(unknown is int) {
                    if (unknownFields == null) {
                      unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                    }
                    unknownFields.MergeVarintField(2, (ulong)(int)unknown);
                  }
                  break;
                }
              }
            }

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


          public bool HasNumber {
            get { return result.hasNumber; }
          }
          public string Number {
            get { return result.Number; }
            set { SetNumber(value); }
          }
          public Builder SetNumber(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            PrepareBuilder();
            result.hasNumber = true;
            result.number_ = value;
            return this;
          }
          public Builder ClearNumber() {
            PrepareBuilder();
            result.hasNumber = false;
            result.number_ = "";
            return this;
          }

          public bool HasType {
            get { return result.hasType; }
          }
          public global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType Type {
            get { return result.Type; }
            set { SetType(value); }
          }
          public Builder SetType(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType value) {
            PrepareBuilder();
            result.hasType = true;
            result.type_ = value;
            return this;
          }
          public Builder ClearType() {
            PrepareBuilder();
            result.hasType = false;
            result.type_ = global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType.HOME;
            return this;
          }
        }
        static PhoneNumber() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.Descriptor, null);
        }
      }

    }
    #endregion

    public const int NameFieldNumber = 1;
    private bool hasName;
    private string name_ = "";
    public bool HasName {
      get { return hasName; }
    }
    public string Name {
      get { return name_; }
    }

    public const int IdFieldNumber = 2;
    private bool hasId;
    private int id_;
    public bool HasId {
      get { return hasId; }
    }
    public int Id {
      get { return id_; }
    }

    public const int EmailFieldNumber = 3;
    private bool hasEmail;
    private string email_ = "";
    public bool HasEmail {
      get { return hasEmail; }
    }
    public string Email {
      get { return email_; }
    }

    public const int PhoneFieldNumber = 4;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> phone_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber>();
    public scg::IList<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> PhoneList {
      get { return phone_; }
    }
    public int PhoneCount {
      get { return phone_.Count; }
    }
    public global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber GetPhone(int index) {
      return phone_[index];
    }

    public override bool IsInitialized {
      get {
        if (!hasName) return false;
        if (!hasId) return false;
        foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber element in PhoneList) {
          if (!element.IsInitialized) return false;
        }
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _personFieldNames;
      if (hasName) {
        output.WriteString(1, field_names[2], Name);
      }
      if (hasId) {
        output.WriteInt32(2, field_names[1], Id);
      }
      if (hasEmail) {
        output.WriteString(3, field_names[0], Email);
      }
      if (phone_.Count > 0) {
        output.WriteMessageArray(4, field_names[3], phone_);
      }
      UnknownFields.WriteTo(output);
    }

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

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

      size = 0;
      if (hasName) {
        size += pb::CodedOutputStream.ComputeStringSize(1, Name);
      }
      if (hasId) {
        size += pb::CodedOutputStream.ComputeInt32Size(2, Id);
      }
      if (hasEmail) {
        size += pb::CodedOutputStream.ComputeStringSize(3, Email);
      }
      foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber element in PhoneList) {
        size += pb::CodedOutputStream.ComputeMessageSize(4, element);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static Person ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static Person ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static Person ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static Person ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static Person ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static Person ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Person ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static Person ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static Person ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static Person ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private Person MakeReadOnly() {
      phone_.MakeReadOnly();
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private Person result;

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

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

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

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

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

      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::Google.ProtocolBuffers.Examples.AddressBook.Person.Descriptor; }
      }

      public override Person DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.Examples.AddressBook.Person.DefaultInstance; }
      }

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

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

      public override Builder MergeFrom(Person other) {
        if (other == global::Google.ProtocolBuffers.Examples.AddressBook.Person.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasName) {
          Name = other.Name;
        }
        if (other.HasId) {
          Id = other.Id;
        }
        if (other.HasEmail) {
          Email = other.Email;
        }
        if (other.phone_.Count != 0) {
          result.phone_.Add(other.phone_);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_personFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _personFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 10: {
              result.hasName = input.ReadString(ref result.name_);
              break;
            }
            case 16: {
              result.hasId = input.ReadInt32(ref result.id_);
              break;
            }
            case 26: {
              result.hasEmail = input.ReadString(ref result.email_);
              break;
            }
            case 34: {
              input.ReadMessageArray(tag, field_name, result.phone_, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.DefaultInstance, extensionRegistry);
              break;
            }
          }
        }

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


      public bool HasName {
        get { return result.hasName; }
      }
      public string Name {
        get { return result.Name; }
        set { SetName(value); }
      }
      public Builder SetName(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasName = true;
        result.name_ = value;
        return this;
      }
      public Builder ClearName() {
        PrepareBuilder();
        result.hasName = false;
        result.name_ = "";
        return this;
      }

      public bool HasId {
        get { return result.hasId; }
      }
      public int Id {
        get { return result.Id; }
        set { SetId(value); }
      }
      public Builder SetId(int value) {
        PrepareBuilder();
        result.hasId = true;
        result.id_ = value;
        return this;
      }
      public Builder ClearId() {
        PrepareBuilder();
        result.hasId = false;
        result.id_ = 0;
        return this;
      }

      public bool HasEmail {
        get { return result.hasEmail; }
      }
      public string Email {
        get { return result.Email; }
        set { SetEmail(value); }
      }
      public Builder SetEmail(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasEmail = true;
        result.email_ = value;
        return this;
      }
      public Builder ClearEmail() {
        PrepareBuilder();
        result.hasEmail = false;
        result.email_ = "";
        return this;
      }

      public pbc::IPopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> PhoneList {
        get { return PrepareBuilder().phone_; }
      }
      public int PhoneCount {
        get { return result.PhoneCount; }
      }
      public global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber GetPhone(int index) {
        return result.GetPhone(index);
      }
      public Builder SetPhone(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.phone_[index] = value;
        return this;
      }
      public Builder SetPhone(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.phone_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddPhone(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.phone_.Add(value);
        return this;
      }
      public Builder AddPhone(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.phone_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneNumber> values) {
        PrepareBuilder();
        result.phone_.Add(values);
        return this;
      }
      public Builder ClearPhone() {
        PrepareBuilder();
        result.phone_.Clear();
        return this;
      }
    }
    static Person() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.Descriptor, null);
    }
  }

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

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

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

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_AddressBook__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<AddressBook, AddressBook.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.internal__static_tutorial_AddressBook__FieldAccessorTable; }
    }

    public const int PersonFieldNumber = 1;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person> person_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person>();
    public scg::IList<global::Google.ProtocolBuffers.Examples.AddressBook.Person> PersonList {
      get { return person_; }
    }
    public int PersonCount {
      get { return person_.Count; }
    }
    public global::Google.ProtocolBuffers.Examples.AddressBook.Person GetPerson(int index) {
      return person_[index];
    }

    public override bool IsInitialized {
      get {
        foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person element in PersonList) {
          if (!element.IsInitialized) return false;
        }
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _addressBookFieldNames;
      if (person_.Count > 0) {
        output.WriteMessageArray(1, field_names[0], person_);
      }
      UnknownFields.WriteTo(output);
    }

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

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

      size = 0;
      foreach (global::Google.ProtocolBuffers.Examples.AddressBook.Person element in PersonList) {
        size += pb::CodedOutputStream.ComputeMessageSize(1, element);
      }
      size += UnknownFields.SerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    public static AddressBook ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AddressBook ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AddressBook ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AddressBook ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AddressBook ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AddressBook ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static AddressBook ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static AddressBook ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static AddressBook ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AddressBook ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private AddressBook MakeReadOnly() {
      person_.MakeReadOnly();
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private AddressBook result;

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

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

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

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

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

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

      public override AddressBook DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook.DefaultInstance; }
      }

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

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

      public override Builder MergeFrom(AddressBook other) {
        if (other == global::Google.ProtocolBuffers.Examples.AddressBook.AddressBook.DefaultInstance) return this;
        PrepareBuilder();
        if (other.person_.Count != 0) {
          result.person_.Add(other.person_);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }

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

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

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


      public pbc::IPopsicleList<global::Google.ProtocolBuffers.Examples.AddressBook.Person> PersonList {
        get { return PrepareBuilder().person_; }
      }
      public int PersonCount {
        get { return result.PersonCount; }
      }
      public global::Google.ProtocolBuffers.Examples.AddressBook.Person GetPerson(int index) {
        return result.GetPerson(index);
      }
      public Builder SetPerson(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.person_[index] = value;
        return this;
      }
      public Builder SetPerson(int index, global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.person_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddPerson(global::Google.ProtocolBuffers.Examples.AddressBook.Person value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.person_.Add(value);
        return this;
      }
      public Builder AddPerson(global::Google.ProtocolBuffers.Examples.AddressBook.Person.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.person_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangePerson(scg::IEnumerable<global::Google.ProtocolBuffers.Examples.AddressBook.Person> values) {
        PrepareBuilder();
        result.person_.Add(values);
        return this;
      }
      public Builder ClearPerson() {
        PrepareBuilder();
        result.person_.Clear();
        return this;
      }
    }
    static AddressBook() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.Examples.AddressBook.Addressbook.Descriptor, null);
    }
  }

  #endregion

}

#endregion Designer generated code
