// 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 UnitTestExtrasLiteProtoFile {
  
    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.EmployeeIdLite);
    }
    #endregion
    #region Extensions
    public const int EmployeeIdLiteFieldNumber = 126;
    public static pb::GeneratedExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite, global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite> EmployeeIdLite;
    #endregion
    
    #region Static variables
    #endregion
    #region Extensions
    internal static readonly object Descriptor;
    static UnitTestExtrasLiteProtoFile() {
      Descriptor = null;
      global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.EmployeeIdLite = 
        new pb::GeneratedExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite, global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite>(
          "protobuf_unittest_extra.employee_id_lite",
          global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.DefaultInstance,
          null,
          global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite.DefaultInstance,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.EmployeeIdLiteFieldNumber,
          pbd::FieldType.Message);
    }
    #endregion
    
  }
  #region Enums
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public enum ExtraEnum {
    DEFAULT = 10,
    EXLITE_FOO = 7,
    EXLITE_BAR = 8,
    EXLITE_BAZ = 9,
  }
  
  #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 TestRequiredLite : pb::GeneratedMessageLite<TestRequiredLite, TestRequiredLite.Builder> {
    private static readonly TestRequiredLite defaultInstance = new Builder().BuildPartial();
    public static TestRequiredLite DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestRequiredLite DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestRequiredLite ThisMessage {
      get { return this; }
    }
    
    public const int DFieldNumber = 1;
    private bool hasD;
    private int d_ = 0;
    public bool HasD {
      get { return hasD; }
    }
    public int D {
      get { return d_; }
    }
    
    public const int EnFieldNumber = 2;
    private bool hasEn;
    private global::Google.ProtocolBuffers.TestProtos.ExtraEnum en_ = global::Google.ProtocolBuffers.TestProtos.ExtraEnum.DEFAULT;
    public bool HasEn {
      get { return hasEn; }
    }
    public global::Google.ProtocolBuffers.TestProtos.ExtraEnum En {
      get { return en_; }
    }
    
    public override bool IsInitialized {
      get {
        if (!hasD) return false;
        if (!hasEn) return false;
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      if (HasD) {
        output.WriteInt32(1, "d", D);
      }
      if (HasEn) {
        output.WriteEnum(2, "en", (int) En, En.ToString());
      }
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (HasD) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, D);
        }
        if (HasEn) {
          size += pb::CodedOutputStream.ComputeEnumSize(2, (int) En);
        }
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      if (hasD) hash ^= d_.GetHashCode();
      if (hasEn) hash ^= en_.GetHashCode();
      return hash;
    }
    
    public override bool Equals(object obj) {
      TestRequiredLite other = obj as TestRequiredLite;
      if (other == null) return false;
      if (hasD != other.hasD || (hasD && !d_.Equals(other.d_))) return false;
      if (hasEn != other.hasEn || (hasEn && !en_.Equals(other.en_))) return false;
      return true;
    }
    
    public override void PrintTo(global::System.IO.TextWriter writer) {
      PrintField("d", hasD, d_, writer);
      PrintField("en", hasEn, en_, writer);
    }
    #endregion
    
    public static TestRequiredLite ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestRequiredLite ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestRequiredLite ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestRequiredLite 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(TestRequiredLite 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::GeneratedBuilderLite<TestRequiredLite, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestRequiredLite result = new TestRequiredLite();
      
      protected override TestRequiredLite MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestRequiredLite();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override TestRequiredLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestRequiredLite.DefaultInstance; }
      }
      
      public override TestRequiredLite BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        TestRequiredLite returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessageLite other) {
        if (other is TestRequiredLite) {
          return MergeFrom((TestRequiredLite) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestRequiredLite other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestRequiredLite.DefaultInstance) return this;
        if (other.HasD) {
          D = other.D;
        }
        if (other.HasEn) {
          En = other.En;
        }
        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) {
        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)) {
                return this;
              }
              ParseUnknownField(input, extensionRegistry, tag);
              break;
            }
            case 8: {
              D = input.ReadInt32();
              break;
            }
            case 16: {
              int rawValue = input.ReadEnum();
              if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.ExtraEnum), rawValue)) {
              } else {
                En = (global::Google.ProtocolBuffers.TestProtos.ExtraEnum) rawValue;
              }
              break;
            }
          }
        }
        
        return this;
      }
      
      
      public bool HasD {
        get { return result.HasD; }
      }
      public int D {
        get { return result.D; }
        set { SetD(value); }
      }
      public Builder SetD(int value) {
        result.hasD = true;
        result.d_ = value;
        return this;
      }
      public Builder ClearD() {
        result.hasD = false;
        result.d_ = 0;
        return this;
      }
      
      public bool HasEn {
       get { return result.HasEn; }
      }
      public global::Google.ProtocolBuffers.TestProtos.ExtraEnum En {
        get { return result.En; }
        set { SetEn(value); }
      }
      public Builder SetEn(global::Google.ProtocolBuffers.TestProtos.ExtraEnum value) {
        result.hasEn = true;
        result.en_ = value;
        return this;
      }
      public Builder ClearEn() {
        result.hasEn = false;
        result.en_ = global::Google.ProtocolBuffers.TestProtos.ExtraEnum.DEFAULT;
        return this;
      }
    }
    static TestRequiredLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.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 TestInteropPersonLite : pb::ExtendableMessageLite<TestInteropPersonLite, TestInteropPersonLite.Builder> {
    private static readonly TestInteropPersonLite defaultInstance = new Builder().BuildPartial();
    public static TestInteropPersonLite DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestInteropPersonLite DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestInteropPersonLite ThisMessage {
      get { return this; }
    }
    
    #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.Runtime.CompilerServices.CompilerGeneratedAttribute()]
      [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
      public enum PhoneType {
        MOBILE = 0,
        HOME = 1,
        WORK = 2,
      }
      
      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
      [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
      public sealed partial class PhoneNumber : pb::GeneratedMessageLite<PhoneNumber, PhoneNumber.Builder> {
        private static readonly PhoneNumber defaultInstance = new Builder().BuildPartial();
        public static PhoneNumber DefaultInstance {
          get { return defaultInstance; }
        }
        
        public override PhoneNumber DefaultInstanceForType {
          get { return defaultInstance; }
        }
        
        protected override PhoneNumber ThisMessage {
          get { return this; }
        }
        
        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.TestProtos.TestInteropPersonLite.Types.PhoneType type_ = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType.HOME;
        public bool HasType {
          get { return hasType; }
        }
        public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType Type {
          get { return type_; }
        }
        
        public override bool IsInitialized {
          get {
            if (!hasNumber) return false;
            return true;
          }
        }
        
        public override void WriteTo(pb::ICodedOutputStream output) {
          int size = SerializedSize;
          if (HasNumber) {
            output.WriteString(1, "number", Number);
          }
          if (HasType) {
            output.WriteEnum(2, "type", (int) Type, Type.ToString());
          }
        }
        
        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            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);
            }
            memoizedSerializedSize = size;
            return size;
          }
        }
        
        #region Lite runtime methods
        public override int GetHashCode() {
          int hash = GetType().GetHashCode();
          if (hasNumber) hash ^= number_.GetHashCode();
          if (hasType) hash ^= type_.GetHashCode();
          return hash;
        }
        
        public override bool Equals(object obj) {
          PhoneNumber other = obj as PhoneNumber;
          if (other == null) return false;
          if (hasNumber != other.hasNumber || (hasNumber && !number_.Equals(other.number_))) return false;
          if (hasType != other.hasType || (hasType && !type_.Equals(other.type_))) return false;
          return true;
        }
        
        public override void PrintTo(global::System.IO.TextWriter writer) {
          PrintField("number", hasNumber, number_, writer);
          PrintField("type", hasType, type_, writer);
        }
        #endregion
        
        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::CodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static PhoneNumber 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(PhoneNumber 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::GeneratedBuilderLite<PhoneNumber, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {}
          
          PhoneNumber result = new PhoneNumber();
          
          protected override PhoneNumber MessageBeingBuilt {
            get { return result; }
          }
          
          public override Builder Clear() {
            result = new PhoneNumber();
            return this;
          }
          
          public override Builder Clone() {
            return new Builder().MergeFrom(result);
          }
          
          public override PhoneNumber DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance; }
          }
          
          public override PhoneNumber BuildPartial() {
            if (result == null) {
              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
            }
            PhoneNumber returnMe = result;
            result = null;
            return returnMe;
          }
          
          public override Builder MergeFrom(pb::IMessageLite 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.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance) return this;
            if (other.HasNumber) {
              Number = other.Number;
            }
            if (other.HasType) {
              Type = other.Type;
            }
            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) {
            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)) {
                    return this;
                  }
                  ParseUnknownField(input, extensionRegistry, tag);
                  break;
                }
                case 10: {
                  Number = input.ReadString();
                  break;
                }
                case 16: {
                  int rawValue = input.ReadEnum();
                  if (!global::System.Enum.IsDefined(typeof(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType), rawValue)) {
                  } else {
                    Type = (global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType) rawValue;
                  }
                  break;
                }
              }
            }
            
            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");
            result.hasNumber = true;
            result.number_ = value;
            return this;
          }
          public Builder ClearNumber() {
            result.hasNumber = false;
            result.number_ = "";
            return this;
          }
          
          public bool HasType {
           get { return result.HasType; }
          }
          public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType Type {
            get { return result.Type; }
            set { SetType(value); }
          }
          public Builder SetType(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType value) {
            result.hasType = true;
            result.type_ = value;
            return this;
          }
          public Builder ClearType() {
            result.hasType = false;
            result.type_ = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType.HOME;
            return this;
          }
        }
        static PhoneNumber() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.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 Addresses : pb::GeneratedMessageLite<Addresses, Addresses.Builder> {
        private static readonly Addresses defaultInstance = new Builder().BuildPartial();
        public static Addresses DefaultInstance {
          get { return defaultInstance; }
        }
        
        public override Addresses DefaultInstanceForType {
          get { return defaultInstance; }
        }
        
        protected override Addresses ThisMessage {
          get { return this; }
        }
        
        public const int AddressFieldNumber = 1;
        private bool hasAddress;
        private string address_ = "";
        public bool HasAddress {
          get { return hasAddress; }
        }
        public string Address {
          get { return address_; }
        }
        
        public const int Address2FieldNumber = 2;
        private bool hasAddress2;
        private string address2_ = "";
        public bool HasAddress2 {
          get { return hasAddress2; }
        }
        public string Address2 {
          get { return address2_; }
        }
        
        public const int CityFieldNumber = 3;
        private bool hasCity;
        private string city_ = "";
        public bool HasCity {
          get { return hasCity; }
        }
        public string City {
          get { return city_; }
        }
        
        public const int StateFieldNumber = 4;
        private bool hasState;
        private string state_ = "";
        public bool HasState {
          get { return hasState; }
        }
        public string State {
          get { return state_; }
        }
        
        public const int ZipFieldNumber = 5;
        private bool hasZip;
        private uint zip_ = 0;
        public bool HasZip {
          get { return hasZip; }
        }
        [global::System.CLSCompliant(false)]
        public uint Zip {
          get { return zip_; }
        }
        
        public override bool IsInitialized {
          get {
            if (!hasAddress) return false;
            if (!hasCity) return false;
            if (!hasState) return false;
            if (!hasZip) return false;
            return true;
          }
        }
        
        public override void WriteTo(pb::ICodedOutputStream output) {
          int size = SerializedSize;
          if (HasAddress) {
            output.WriteString(1, "address", Address);
          }
          if (HasAddress2) {
            output.WriteString(2, "address2", Address2);
          }
          if (HasCity) {
            output.WriteString(3, "city", City);
          }
          if (HasState) {
            output.WriteString(4, "state", State);
          }
          if (HasZip) {
            output.WriteFixed32(5, "zip", Zip);
          }
        }
        
        private int memoizedSerializedSize = -1;
        public override int SerializedSize {
          get {
            int size = memoizedSerializedSize;
            if (size != -1) return size;
            
            size = 0;
            if (HasAddress) {
              size += pb::CodedOutputStream.ComputeStringSize(1, Address);
            }
            if (HasAddress2) {
              size += pb::CodedOutputStream.ComputeStringSize(2, Address2);
            }
            if (HasCity) {
              size += pb::CodedOutputStream.ComputeStringSize(3, City);
            }
            if (HasState) {
              size += pb::CodedOutputStream.ComputeStringSize(4, State);
            }
            if (HasZip) {
              size += pb::CodedOutputStream.ComputeFixed32Size(5, Zip);
            }
            memoizedSerializedSize = size;
            return size;
          }
        }
        
        #region Lite runtime methods
        public override int GetHashCode() {
          int hash = GetType().GetHashCode();
          if (hasAddress) hash ^= address_.GetHashCode();
          if (hasAddress2) hash ^= address2_.GetHashCode();
          if (hasCity) hash ^= city_.GetHashCode();
          if (hasState) hash ^= state_.GetHashCode();
          if (hasZip) hash ^= zip_.GetHashCode();
          return hash;
        }
        
        public override bool Equals(object obj) {
          Addresses other = obj as Addresses;
          if (other == null) return false;
          if (hasAddress != other.hasAddress || (hasAddress && !address_.Equals(other.address_))) return false;
          if (hasAddress2 != other.hasAddress2 || (hasAddress2 && !address2_.Equals(other.address2_))) return false;
          if (hasCity != other.hasCity || (hasCity && !city_.Equals(other.city_))) return false;
          if (hasState != other.hasState || (hasState && !state_.Equals(other.state_))) return false;
          if (hasZip != other.hasZip || (hasZip && !zip_.Equals(other.zip_))) return false;
          return true;
        }
        
        public override void PrintTo(global::System.IO.TextWriter writer) {
          PrintField("address", hasAddress, address_, writer);
          PrintField("address2", hasAddress2, address2_, writer);
          PrintField("city", hasCity, city_, writer);
          PrintField("state", hasState, state_, writer);
          PrintField("zip", hasZip, zip_, writer);
        }
        #endregion
        
        public static Addresses ParseFrom(pb::ByteString data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static Addresses ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static Addresses ParseFrom(byte[] data) {
          return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
        }
        public static Addresses ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
        }
        public static Addresses ParseFrom(global::System.IO.Stream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static Addresses ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        public static Addresses ParseDelimitedFrom(global::System.IO.Stream input) {
          return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
        }
        public static Addresses ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
          return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
        }
        public static Addresses ParseFrom(pb::CodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static Addresses 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(Addresses 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::GeneratedBuilderLite<Addresses, Builder> {
          protected override Builder ThisBuilder {
            get { return this; }
          }
          public Builder() {}
          
          Addresses result = new Addresses();
          
          protected override Addresses MessageBeingBuilt {
            get { return result; }
          }
          
          public override Builder Clear() {
            result = new Addresses();
            return this;
          }
          
          public override Builder Clone() {
            return new Builder().MergeFrom(result);
          }
          
          public override Addresses DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance; }
          }
          
          public override Addresses BuildPartial() {
            if (result == null) {
              throw new global::System.InvalidOperationException("build() has already been called on this Builder");
            }
            Addresses returnMe = result;
            result = null;
            return returnMe;
          }
          
          public override Builder MergeFrom(pb::IMessageLite other) {
            if (other is Addresses) {
              return MergeFrom((Addresses) other);
            } else {
              base.MergeFrom(other);
              return this;
            }
          }
          
          public override Builder MergeFrom(Addresses other) {
            if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance) return this;
            if (other.HasAddress) {
              Address = other.Address;
            }
            if (other.HasAddress2) {
              Address2 = other.Address2;
            }
            if (other.HasCity) {
              City = other.City;
            }
            if (other.HasState) {
              State = other.State;
            }
            if (other.HasZip) {
              Zip = other.Zip;
            }
            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) {
            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)) {
                    return this;
                  }
                  ParseUnknownField(input, extensionRegistry, tag);
                  break;
                }
                case 10: {
                  Address = input.ReadString();
                  break;
                }
                case 18: {
                  Address2 = input.ReadString();
                  break;
                }
                case 26: {
                  City = input.ReadString();
                  break;
                }
                case 34: {
                  State = input.ReadString();
                  break;
                }
                case 45: {
                  Zip = input.ReadFixed32();
                  break;
                }
              }
            }
            
            return this;
          }
          
          
          public bool HasAddress {
            get { return result.HasAddress; }
          }
          public string Address {
            get { return result.Address; }
            set { SetAddress(value); }
          }
          public Builder SetAddress(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasAddress = true;
            result.address_ = value;
            return this;
          }
          public Builder ClearAddress() {
            result.hasAddress = false;
            result.address_ = "";
            return this;
          }
          
          public bool HasAddress2 {
            get { return result.HasAddress2; }
          }
          public string Address2 {
            get { return result.Address2; }
            set { SetAddress2(value); }
          }
          public Builder SetAddress2(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasAddress2 = true;
            result.address2_ = value;
            return this;
          }
          public Builder ClearAddress2() {
            result.hasAddress2 = false;
            result.address2_ = "";
            return this;
          }
          
          public bool HasCity {
            get { return result.HasCity; }
          }
          public string City {
            get { return result.City; }
            set { SetCity(value); }
          }
          public Builder SetCity(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasCity = true;
            result.city_ = value;
            return this;
          }
          public Builder ClearCity() {
            result.hasCity = false;
            result.city_ = "";
            return this;
          }
          
          public bool HasState {
            get { return result.HasState; }
          }
          public string State {
            get { return result.State; }
            set { SetState(value); }
          }
          public Builder SetState(string value) {
            pb::ThrowHelper.ThrowIfNull(value, "value");
            result.hasState = true;
            result.state_ = value;
            return this;
          }
          public Builder ClearState() {
            result.hasState = false;
            result.state_ = "";
            return this;
          }
          
          public bool HasZip {
            get { return result.HasZip; }
          }
          [global::System.CLSCompliant(false)]
          public uint Zip {
            get { return result.Zip; }
            set { SetZip(value); }
          }
          [global::System.CLSCompliant(false)]
          public Builder SetZip(uint value) {
            result.hasZip = true;
            result.zip_ = value;
            return this;
          }
          public Builder ClearZip() {
            result.hasZip = false;
            result.zip_ = 0;
            return this;
          }
        }
        static Addresses() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.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_ = 0;
    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 CodesFieldNumber = 10;
    private int codesMemoizedSerializedSize;
    private pbc::PopsicleList<int> codes_ = new pbc::PopsicleList<int>();
    public scg::IList<int> CodesList {
      get { return pbc::Lists.AsReadOnly(codes_); }
    }
    public int CodesCount {
      get { return codes_.Count; }
    }
    public int GetCodes(int index) {
      return codes_[index];
    }
    
    public const int PhoneFieldNumber = 4;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> phone_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> PhoneList {
      get { return phone_; }
    }
    public int PhoneCount {
      get { return phone_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber GetPhone(int index) {
      return phone_[index];
    }
    
    public const int AddressesFieldNumber = 5;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> addresses_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> AddressesList {
      get { return addresses_; }
    }
    public int AddressesCount {
      get { return addresses_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses GetAddresses(int index) {
      return addresses_[index];
    }
    
    public override bool IsInitialized {
      get {
        if (!hasName) return false;
        if (!hasId) return false;
        foreach (global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber element in PhoneList) {
          if (!element.IsInitialized) return false;
        }
        if (!ExtensionsAreInitialized) return false;
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      pb::ExtendableMessageLite<TestInteropPersonLite, TestInteropPersonLite.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      if (HasName) {
        output.WriteString(1, "name", Name);
      }
      if (HasId) {
        output.WriteInt32(2, "id", Id);
      }
      if (HasEmail) {
        output.WriteString(3, "email", Email);
      }
      if (phone_.Count > 0) {
        output.WriteArray(pbd::FieldType.Message, 4, "phone", phone_);
      }
      if (addresses_.Count > 0) {
        output.WriteArray(pbd::FieldType.Group, 5, "addresses", addresses_);
      }
      if (codes_.Count > 0) {
        output.WritePackedArray(pbd::FieldType.Int32, 10, "codes", codesMemoizedSerializedSize, codes_);
      }
      extensionWriter.WriteUntil(200, output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        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);
        }
        {
          int dataSize = 0;
          foreach (int element in CodesList) {
            dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
          }
          size += dataSize;
          if (codes_.Count != 0) {
            size += 1 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);
          }
          codesMemoizedSerializedSize = dataSize;
        }
        foreach (global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber element in PhoneList) {
          size += pb::CodedOutputStream.ComputeMessageSize(4, element);
        }
        foreach (global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses element in AddressesList) {
          size += pb::CodedOutputStream.ComputeGroupSize(5, element);
        }
        size += ExtensionsSerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      if (hasName) hash ^= name_.GetHashCode();
      if (hasId) hash ^= id_.GetHashCode();
      if (hasEmail) hash ^= email_.GetHashCode();
      foreach(int i in codes_)
        hash ^= i.GetHashCode();
      foreach(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber i in phone_)
        hash ^= i.GetHashCode();
      foreach(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses i in addresses_)
        hash ^= i.GetHashCode();
      hash ^= base.GetHashCode();
      return hash;
    }
    
    public override bool Equals(object obj) {
      TestInteropPersonLite other = obj as TestInteropPersonLite;
      if (other == null) return false;
      if (hasName != other.hasName || (hasName && !name_.Equals(other.name_))) return false;
      if (hasId != other.hasId || (hasId && !id_.Equals(other.id_))) return false;
      if (hasEmail != other.hasEmail || (hasEmail && !email_.Equals(other.email_))) return false;
      if(codes_.Count != other.codes_.Count) return false;
      for(int ix=0; ix < codes_.Count; ix++)
        if(!codes_[ix].Equals(other.codes_[ix])) return false;
      if(phone_.Count != other.phone_.Count) return false;
      for(int ix=0; ix < phone_.Count; ix++)
        if(!phone_[ix].Equals(other.phone_[ix])) return false;
      if(addresses_.Count != other.addresses_.Count) return false;
      for(int ix=0; ix < addresses_.Count; ix++)
        if(!addresses_[ix].Equals(other.addresses_[ix])) return false;
      if (!base.Equals(other)) return false;
      return true;
    }
    
    public override void PrintTo(global::System.IO.TextWriter writer) {
      PrintField("name", hasName, name_, writer);
      PrintField("id", hasId, id_, writer);
      PrintField("email", hasEmail, email_, writer);
      PrintField("phone", phone_, writer);
      PrintField("Addresses", addresses_, writer);
      PrintField("codes", codes_, writer);
      base.PrintTo(writer);
    }
    #endregion
    
    public static TestInteropPersonLite ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestInteropPersonLite ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestInteropPersonLite ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestInteropPersonLite 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(TestInteropPersonLite 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::ExtendableBuilderLite<TestInteropPersonLite, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestInteropPersonLite result = new TestInteropPersonLite();
      
      protected override TestInteropPersonLite MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestInteropPersonLite();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override TestInteropPersonLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.DefaultInstance; }
      }
      
      public override TestInteropPersonLite BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.codes_.MakeReadOnly();
        result.phone_.MakeReadOnly();
        result.addresses_.MakeReadOnly();
        TestInteropPersonLite returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessageLite other) {
        if (other is TestInteropPersonLite) {
          return MergeFrom((TestInteropPersonLite) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestInteropPersonLite other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.DefaultInstance) return this;
        if (other.HasName) {
          Name = other.Name;
        }
        if (other.HasId) {
          Id = other.Id;
        }
        if (other.HasEmail) {
          Email = other.Email;
        }
        if (other.codes_.Count != 0) {
          base.AddRange(other.codes_, result.codes_);
        }
        if (other.phone_.Count != 0) {
          base.AddRange(other.phone_, result.phone_);
        }
        if (other.addresses_.Count != 0) {
          base.AddRange(other.addresses_, result.addresses_);
        }
          this.MergeExtensionFields(other);
        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) {
        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)) {
                return this;
              }
              ParseUnknownField(input, extensionRegistry, tag);
              break;
            }
            case 10: {
              Name = input.ReadString();
              break;
            }
            case 16: {
              Id = input.ReadInt32();
              break;
            }
            case 26: {
              Email = input.ReadString();
              break;
            }
            case 34: {
              global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.CreateBuilder();
              input.ReadMessage(subBuilder, extensionRegistry);
              AddPhone(subBuilder.BuildPartial());
              break;
            }
            case 43: {
              global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.CreateBuilder();
              input.ReadGroup(5, subBuilder, extensionRegistry);
              AddAddresses(subBuilder.BuildPartial());
              break;
            }
            case 82: {
              int length = input.ReadInt32();
              int limit = input.PushLimit(length);
              while (!input.ReachedLimit) {
                AddCodes(input.ReadInt32());
              }
              input.PopLimit(limit);
              break;
            }
          }
        }
        
        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");
        result.hasName = true;
        result.name_ = value;
        return this;
      }
      public Builder ClearName() {
        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) {
        result.hasId = true;
        result.id_ = value;
        return this;
      }
      public Builder ClearId() {
        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");
        result.hasEmail = true;
        result.email_ = value;
        return this;
      }
      public Builder ClearEmail() {
        result.hasEmail = false;
        result.email_ = "";
        return this;
      }
      
      public pbc::IPopsicleList<int> CodesList {
        get { return result.codes_; }
      }
      public int CodesCount {
        get { return result.CodesCount; }
      }
      public int GetCodes(int index) {
        return result.GetCodes(index);
      }
      public Builder SetCodes(int index, int value) {
        result.codes_[index] = value;
        return this;
      }
      public Builder AddCodes(int value) {
        result.codes_.Add(value);
        return this;
      }
      public Builder AddRangeCodes(scg::IEnumerable<int> values) {
        base.AddRange(values, result.codes_);
        return this;
      }
      public Builder ClearCodes() {
        result.codes_.Clear();
        return this;
      }
      
      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> PhoneList {
        get { return result.phone_; }
      }
      public int PhoneCount {
        get { return result.PhoneCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber GetPhone(int index) {
        return result.GetPhone(index);
      }
      public Builder SetPhone(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.phone_[index] = value;
        return this;
      }
      public Builder SetPhone(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.phone_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.phone_.Add(value);
        return this;
      }
      public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.phone_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> values) {
        base.AddRange(values, result.phone_);
        return this;
      }
      public Builder ClearPhone() {
        result.phone_.Clear();
        return this;
      }
      
      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> AddressesList {
        get { return result.addresses_; }
      }
      public int AddressesCount {
        get { return result.AddressesCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses GetAddresses(int index) {
        return result.GetAddresses(index);
      }
      public Builder SetAddresses(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.addresses_[index] = value;
        return this;
      }
      public Builder SetAddresses(int index, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.addresses_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.addresses_.Add(value);
        return this;
      }
      public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.addresses_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangeAddresses(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> values) {
        base.AddRange(values, result.addresses_);
        return this;
      }
      public Builder ClearAddresses() {
        result.addresses_.Clear();
        return this;
      }
    }
    static TestInteropPersonLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.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 TestInteropEmployeeIdLite : pb::GeneratedMessageLite<TestInteropEmployeeIdLite, TestInteropEmployeeIdLite.Builder> {
    private static readonly TestInteropEmployeeIdLite defaultInstance = new Builder().BuildPartial();
    public static TestInteropEmployeeIdLite DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override TestInteropEmployeeIdLite DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override TestInteropEmployeeIdLite ThisMessage {
      get { return this; }
    }
    
    public const int NumberFieldNumber = 1;
    private bool hasNumber;
    private string number_ = "";
    public bool HasNumber {
      get { return hasNumber; }
    }
    public string 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.WriteString(1, "number", Number);
      }
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (HasNumber) {
          size += pb::CodedOutputStream.ComputeStringSize(1, Number);
        }
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      if (hasNumber) hash ^= number_.GetHashCode();
      return hash;
    }
    
    public override bool Equals(object obj) {
      TestInteropEmployeeIdLite other = obj as TestInteropEmployeeIdLite;
      if (other == null) return false;
      if (hasNumber != other.hasNumber || (hasNumber && !number_.Equals(other.number_))) return false;
      return true;
    }
    
    public override void PrintTo(global::System.IO.TextWriter writer) {
      PrintField("number", hasNumber, number_, writer);
    }
    #endregion
    
    public static TestInteropEmployeeIdLite ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(pb::CodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite 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(TestInteropEmployeeIdLite 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::GeneratedBuilderLite<TestInteropEmployeeIdLite, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      TestInteropEmployeeIdLite result = new TestInteropEmployeeIdLite();
      
      protected override TestInteropEmployeeIdLite MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new TestInteropEmployeeIdLite();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override TestInteropEmployeeIdLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite.DefaultInstance; }
      }
      
      public override TestInteropEmployeeIdLite BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        TestInteropEmployeeIdLite returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessageLite other) {
        if (other is TestInteropEmployeeIdLite) {
          return MergeFrom((TestInteropEmployeeIdLite) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(TestInteropEmployeeIdLite other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite.DefaultInstance) return this;
        if (other.HasNumber) {
          Number = other.Number;
        }
        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) {
        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)) {
                return this;
              }
              ParseUnknownField(input, extensionRegistry, tag);
              break;
            }
            case 10: {
              Number = input.ReadString();
              break;
            }
          }
        }
        
        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");
        result.hasNumber = true;
        result.number_ = value;
        return this;
      }
      public Builder ClearNumber() {
        result.hasNumber = false;
        result.number_ = "";
        return this;
      }
    }
    static TestInteropEmployeeIdLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestExtrasLiteProtoFile.Descriptor, null);
    }
  }
  
  #endregion
  
}
