// 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, field_name);
              break;
            }
            case 8: {
              result.hasD |= input.ReadInt32(ref result.d_);
              break;
            }
            case 16: {
              object unknown;
              if(input.ReadEnum(ref result.en_, out unknown)) {
                result.hasEn = true;
              } else if(unknown is int) {
              }
              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, 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) {
                  }
                  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, field_name);
                  break;
                }
                case 10: {
                  result.hasAddress |= input.ReadString(ref result.address_);
                  break;
                }
                case 18: {
                  result.hasAddress2 |= input.ReadString(ref result.address2_);
                  break;
                }
                case 26: {
                  result.hasCity |= input.ReadString(ref result.city_);
                  break;
                }
                case 34: {
                  result.hasState |= input.ReadString(ref result.state_);
                  break;
                }
                case 45: {
                  result.hasZip |= input.ReadFixed32(ref result.zip_);
                  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, 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.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance, extensionRegistry);
              break;
            }
            case 43: {
              input.ReadGroupArray(tag, field_name, result.addresses_, global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance, extensionRegistry);
              break;
            }
            case 82: {
              input.ReadPrimitiveArray(pbd::FieldType.Int32, tag, field_name, result.codes_);
              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, field_name);
              break;
            }
            case 10: {
              result.hasNumber |= input.ReadString(ref result.number_);
              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
  
}
