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

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

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

    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.EmployeeIdLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedInt32ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedInt64ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedUint32ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedUint64ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSint32ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSint64ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFixed32ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFixed64ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSfixed32ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSfixed64ExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFloatExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedDoubleExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedBoolExtensionLite);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedEnumExtensionLite);
    }
    #endregion
    #region Extensions
    public const int EmployeeIdLiteFieldNumber = 126;
    public static pb::GeneratedExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite, global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite> EmployeeIdLite;
    public const int UnpackedInt32ExtensionLiteFieldNumber = 90;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, int> UnpackedInt32ExtensionLite;
    public const int UnpackedInt64ExtensionLiteFieldNumber = 91;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, long> UnpackedInt64ExtensionLite;
    public const int UnpackedUint32ExtensionLiteFieldNumber = 92;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, uint> UnpackedUint32ExtensionLite;
    public const int UnpackedUint64ExtensionLiteFieldNumber = 93;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, ulong> UnpackedUint64ExtensionLite;
    public const int UnpackedSint32ExtensionLiteFieldNumber = 94;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, int> UnpackedSint32ExtensionLite;
    public const int UnpackedSint64ExtensionLiteFieldNumber = 95;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, long> UnpackedSint64ExtensionLite;
    public const int UnpackedFixed32ExtensionLiteFieldNumber = 96;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, uint> UnpackedFixed32ExtensionLite;
    public const int UnpackedFixed64ExtensionLiteFieldNumber = 97;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, ulong> UnpackedFixed64ExtensionLite;
    public const int UnpackedSfixed32ExtensionLiteFieldNumber = 98;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, int> UnpackedSfixed32ExtensionLite;
    public const int UnpackedSfixed64ExtensionLiteFieldNumber = 99;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, long> UnpackedSfixed64ExtensionLite;
    public const int UnpackedFloatExtensionLiteFieldNumber = 100;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, float> UnpackedFloatExtensionLite;
    public const int UnpackedDoubleExtensionLiteFieldNumber = 101;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, double> UnpackedDoubleExtensionLite;
    public const int UnpackedBoolExtensionLiteFieldNumber = 102;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, bool> UnpackedBoolExtensionLite;
    public const int UnpackedEnumExtensionLiteFieldNumber = 103;
    public static pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite> UnpackedEnumExtensionLite;
    #endregion

    #region Static variables
    #endregion
    #region Extensions
    internal static readonly object Descriptor;
    static UnittestExtrasLite() {
      Descriptor = null;
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.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.UnittestExtrasLite.EmployeeIdLiteFieldNumber,
          pbd::FieldType.Message);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedInt32ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, int>(
          "protobuf_unittest_extra.unpacked_int32_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedInt32ExtensionLiteFieldNumber,
          pbd::FieldType.Int32,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedInt64ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, long>(
          "protobuf_unittest_extra.unpacked_int64_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedInt64ExtensionLiteFieldNumber,
          pbd::FieldType.Int64,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedUint32ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, uint>(
          "protobuf_unittest_extra.unpacked_uint32_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedUint32ExtensionLiteFieldNumber,
          pbd::FieldType.UInt32,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedUint64ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, ulong>(
          "protobuf_unittest_extra.unpacked_uint64_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedUint64ExtensionLiteFieldNumber,
          pbd::FieldType.UInt64,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSint32ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, int>(
          "protobuf_unittest_extra.unpacked_sint32_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSint32ExtensionLiteFieldNumber,
          pbd::FieldType.SInt32,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSint64ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, long>(
          "protobuf_unittest_extra.unpacked_sint64_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSint64ExtensionLiteFieldNumber,
          pbd::FieldType.SInt64,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFixed32ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, uint>(
          "protobuf_unittest_extra.unpacked_fixed32_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFixed32ExtensionLiteFieldNumber,
          pbd::FieldType.Fixed32,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFixed64ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, ulong>(
          "protobuf_unittest_extra.unpacked_fixed64_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFixed64ExtensionLiteFieldNumber,
          pbd::FieldType.Fixed64,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSfixed32ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, int>(
          "protobuf_unittest_extra.unpacked_sfixed32_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSfixed32ExtensionLiteFieldNumber,
          pbd::FieldType.SFixed32,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSfixed64ExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, long>(
          "protobuf_unittest_extra.unpacked_sfixed64_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedSfixed64ExtensionLiteFieldNumber,
          pbd::FieldType.SFixed64,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFloatExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, float>(
          "protobuf_unittest_extra.unpacked_float_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedFloatExtensionLiteFieldNumber,
          pbd::FieldType.Float,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedDoubleExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, double>(
          "protobuf_unittest_extra.unpacked_double_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedDoubleExtensionLiteFieldNumber,
          pbd::FieldType.Double,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedBoolExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, bool>(
          "protobuf_unittest_extra.unpacked_bool_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          null,
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedBoolExtensionLiteFieldNumber,
          pbd::FieldType.Bool,
          false);
      global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedEnumExtensionLite = 
        new pb::GeneratedRepeatExtensionLite<global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite, global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite>(
          "protobuf_unittest_extra.unpacked_enum_extension_lite",
          global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance,
          null,
          new EnumLiteMap<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite>(),
          global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.UnpackedEnumExtensionLiteFieldNumber,
          pbd::FieldType.Enum,
          false);
    }
    #endregion

  }
  #region Enums
  public enum ExtraEnum {
    DEFAULT = 10,
    EXLITE_FOO = 7,
    EXLITE_BAR = 8,
    EXLITE_BAZ = 9,
  }

  public enum UnpackedTypesForeignEnumLite {
    FOREIGN_LITE_FOO = 4,
    FOREIGN_LITE_BAR = 5,
    FOREIGN_LITE_BAZ = 6,
  }

  #endregion

  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestRequiredLite : pb::GeneratedMessageLite<TestRequiredLite, TestRequiredLite.Builder> {
    private TestRequiredLite() { }
    private static readonly TestRequiredLite defaultInstance = new TestRequiredLite().MakeReadOnly();
    private static readonly string[] _testRequiredLiteFieldNames = new string[] { "d", "en" };
    private static readonly uint[] _testRequiredLiteFieldTags = new uint[] { 8, 16 };
    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_;
    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) {
      CalcSerializedSize();
      string[] field_names = _testRequiredLiteFieldNames;
      if (hasD) {
        output.WriteInt32(1, field_names[0], D);
      }
      if (hasEn) {
        output.WriteEnum(2, field_names[1], (int) En, En);
      }
    }

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

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

      size = 0;
      if (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::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestRequiredLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestRequiredLite MakeReadOnly() {
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private TestRequiredLite result;

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

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

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

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

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

      public override TestRequiredLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestRequiredLite.DefaultInstance; }
      }

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

      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;
        PrepareBuilder();
        if (other.HasD) {
          D = other.D;
        }
        if (other.HasEn) {
          En = other.En;
        }
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_testRequiredLiteFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _testRequiredLiteFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          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) {
        PrepareBuilder();
        result.hasD = true;
        result.d_ = value;
        return this;
      }
      public Builder ClearD() {
        PrepareBuilder();
        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) {
        PrepareBuilder();
        result.hasEn = true;
        result.en_ = value;
        return this;
      }
      public Builder ClearEn() {
        PrepareBuilder();
        result.hasEn = false;
        result.en_ = global::Google.ProtocolBuffers.TestProtos.ExtraEnum.DEFAULT;
        return this;
      }
    }
    static TestRequiredLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestInteropPersonLite : pb::ExtendableMessageLite<TestInteropPersonLite, TestInteropPersonLite.Builder> {
    private TestInteropPersonLite() { }
    private static readonly TestInteropPersonLite defaultInstance = new TestInteropPersonLite().MakeReadOnly();
    private static readonly string[] _testInteropPersonLiteFieldNames = new string[] { "addresses", "codes", "email", "id", "name", "phone" };
    private static readonly uint[] _testInteropPersonLiteFieldTags = new uint[] { 43, 82, 26, 16, 10, 34 };
    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()]
    public static partial class Types {
      public enum PhoneType {
        MOBILE = 0,
        HOME = 1,
        WORK = 2,
      }

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

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

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

        public 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) {
          CalcSerializedSize();
          string[] field_names = _phoneNumberFieldNames;
          if (hasNumber) {
            output.WriteString(1, field_names[0], Number);
          }
          if (hasType) {
            output.WriteEnum(2, field_names[1], (int) Type, Type);
          }
        }

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

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

          size = 0;
          if (hasNumber) {
            size += pb::CodedOutputStream.ComputeStringSize(1, Number);
          }
          if (hasType) {
            size += pb::CodedOutputStream.ComputeEnumSize(2, (int) Type);
          }
          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::ICodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static PhoneNumber ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        private PhoneNumber MakeReadOnly() {
          return this;
        }

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

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

          private bool resultIsReadOnly;
          private PhoneNumber result;

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

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

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

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

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

          public override PhoneNumber DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.DefaultInstance; }
          }

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

          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;
            PrepareBuilder();
            if (other.HasNumber) {
              Number = other.Number;
            }
            if (other.HasType) {
              Type = other.Type;
            }
            return this;
          }

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

          public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            PrepareBuilder();
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              if(tag == 0 && field_name != null) {
                int field_ordinal = global::System.Array.BinarySearch(_phoneNumberFieldNames, field_name, global::System.StringComparer.Ordinal);
                if(field_ordinal >= 0)
                  tag = _phoneNumberFieldTags[field_ordinal];
                else {
                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                  continue;
                }
              }
              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");
            PrepareBuilder();
            result.hasNumber = true;
            result.number_ = value;
            return this;
          }
          public Builder ClearNumber() {
            PrepareBuilder();
            result.hasNumber = false;
            result.number_ = "";
            return this;
          }

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

      [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
      public sealed partial class Addresses : pb::GeneratedMessageLite<Addresses, Addresses.Builder> {
        private Addresses() { }
        private static readonly Addresses defaultInstance = new Addresses().MakeReadOnly();
        private static readonly string[] _addressesFieldNames = new string[] { "address", "address2", "city", "state", "zip" };
        private static readonly uint[] _addressesFieldTags = new uint[] { 10, 18, 26, 34, 45 };
        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_;
        public bool HasZip {
          get { return hasZip; }
        }
        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) {
          CalcSerializedSize();
          string[] field_names = _addressesFieldNames;
          if (hasAddress) {
            output.WriteString(1, field_names[0], Address);
          }
          if (hasAddress2) {
            output.WriteString(2, field_names[1], Address2);
          }
          if (hasCity) {
            output.WriteString(3, field_names[2], City);
          }
          if (hasState) {
            output.WriteString(4, field_names[3], State);
          }
          if (hasZip) {
            output.WriteFixed32(5, field_names[4], Zip);
          }
        }

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

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

          size = 0;
          if (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::ICodedInputStream input) {
          return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
        }
        public static Addresses ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
          return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
        }
        private Addresses MakeReadOnly() {
          return this;
        }

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

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

          private bool resultIsReadOnly;
          private Addresses result;

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

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

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

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

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

          public override Addresses DefaultInstanceForType {
            get { return global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.DefaultInstance; }
          }

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

          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;
            PrepareBuilder();
            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::ICodedInputStream input) {
            return MergeFrom(input, pb::ExtensionRegistry.Empty);
          }

          public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
            PrepareBuilder();
            uint tag;
            string field_name;
            while (input.ReadTag(out tag, out field_name)) {
              if(tag == 0 && field_name != null) {
                int field_ordinal = global::System.Array.BinarySearch(_addressesFieldNames, field_name, global::System.StringComparer.Ordinal);
                if(field_ordinal >= 0)
                  tag = _addressesFieldTags[field_ordinal];
                else {
                  ParseUnknownField(input, extensionRegistry, tag, field_name);
                  continue;
                }
              }
              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");
            PrepareBuilder();
            result.hasAddress = true;
            result.address_ = value;
            return this;
          }
          public Builder ClearAddress() {
            PrepareBuilder();
            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");
            PrepareBuilder();
            result.hasAddress2 = true;
            result.address2_ = value;
            return this;
          }
          public Builder ClearAddress2() {
            PrepareBuilder();
            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");
            PrepareBuilder();
            result.hasCity = true;
            result.city_ = value;
            return this;
          }
          public Builder ClearCity() {
            PrepareBuilder();
            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");
            PrepareBuilder();
            result.hasState = true;
            result.state_ = value;
            return this;
          }
          public Builder ClearState() {
            PrepareBuilder();
            result.hasState = false;
            result.state_ = "";
            return this;
          }

          public bool HasZip {
            get { return result.hasZip; }
          }
          public uint Zip {
            get { return result.Zip; }
            set { SetZip(value); }
          }
          public Builder SetZip(uint value) {
            PrepareBuilder();
            result.hasZip = true;
            result.zip_ = value;
            return this;
          }
          public Builder ClearZip() {
            PrepareBuilder();
            result.hasZip = false;
            result.zip_ = 0;
            return this;
          }
        }
        static Addresses() {
          object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
        }
      }

    }
    #endregion

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

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

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

    public const int 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) {
      CalcSerializedSize();
      string[] field_names = _testInteropPersonLiteFieldNames;
      pb::ExtendableMessageLite<TestInteropPersonLite, TestInteropPersonLite.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      if (hasName) {
        output.WriteString(1, field_names[4], Name);
      }
      if (hasId) {
        output.WriteInt32(2, field_names[3], Id);
      }
      if (hasEmail) {
        output.WriteString(3, field_names[2], Email);
      }
      if (phone_.Count > 0) {
        output.WriteMessageArray(4, field_names[5], phone_);
      }
      if (addresses_.Count > 0) {
        output.WriteGroupArray(5, field_names[0], addresses_);
      }
      if (codes_.Count > 0) {
        output.WritePackedInt32Array(10, field_names[1], codesMemoizedSerializedSize, codes_);
      }
      extensionWriter.WriteUntil(200, output);
    }

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

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

      size = 0;
      if (hasName) {
        size += pb::CodedOutputStream.ComputeStringSize(1, Name);
      }
      if (hasId) {
        size += pb::CodedOutputStream.ComputeInt32Size(2, Id);
      }
      if (hasEmail) {
        size += pb::CodedOutputStream.ComputeStringSize(3, Email);
      }
      {
        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::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestInteropPersonLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestInteropPersonLite MakeReadOnly() {
      codes_.MakeReadOnly();
      phone_.MakeReadOnly();
      addresses_.MakeReadOnly();
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private TestInteropPersonLite result;

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

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

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

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

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

      public override TestInteropPersonLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.DefaultInstance; }
      }

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

      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;
        PrepareBuilder();
        if (other.HasName) {
          Name = other.Name;
        }
        if (other.HasId) {
          Id = other.Id;
        }
        if (other.HasEmail) {
          Email = other.Email;
        }
        if (other.codes_.Count != 0) {
          result.codes_.Add(other.codes_);
        }
        if (other.phone_.Count != 0) {
          result.phone_.Add(other.phone_);
        }
        if (other.addresses_.Count != 0) {
          result.addresses_.Add(other.addresses_);
        }
          this.MergeExtensionFields(other);
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_testInteropPersonLiteFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _testInteropPersonLiteFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          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:
            case 80: {
              input.ReadInt32Array(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");
        PrepareBuilder();
        result.hasName = true;
        result.name_ = value;
        return this;
      }
      public Builder ClearName() {
        PrepareBuilder();
        result.hasName = false;
        result.name_ = "";
        return this;
      }

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

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

      public pbc::IPopsicleList<int> CodesList {
        get { return PrepareBuilder().codes_; }
      }
      public int CodesCount {
        get { return result.CodesCount; }
      }
      public int GetCodes(int index) {
        return result.GetCodes(index);
      }
      public Builder SetCodes(int index, int value) {
        PrepareBuilder();
        result.codes_[index] = value;
        return this;
      }
      public Builder AddCodes(int value) {
        PrepareBuilder();
        result.codes_.Add(value);
        return this;
      }
      public Builder AddRangeCodes(scg::IEnumerable<int> values) {
        PrepareBuilder();
        result.codes_.Add(values);
        return this;
      }
      public Builder ClearCodes() {
        PrepareBuilder();
        result.codes_.Clear();
        return this;
      }

      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> PhoneList {
        get { return PrepareBuilder().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");
        PrepareBuilder();
        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");
        PrepareBuilder();
        result.phone_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.phone_.Add(value);
        return this;
      }
      public Builder AddPhone(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.phone_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangePhone(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneNumber> values) {
        PrepareBuilder();
        result.phone_.Add(values);
        return this;
      }
      public Builder ClearPhone() {
        PrepareBuilder();
        result.phone_.Clear();
        return this;
      }

      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> AddressesList {
        get { return PrepareBuilder().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");
        PrepareBuilder();
        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");
        PrepareBuilder();
        result.addresses_[index] = builderForValue.Build();
        return this;
      }
      public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.addresses_.Add(value);
        return this;
      }
      public Builder AddAddresses(global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.addresses_.Add(builderForValue.Build());
        return this;
      }
      public Builder AddRangeAddresses(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.Addresses> values) {
        PrepareBuilder();
        result.addresses_.Add(values);
        return this;
      }
      public Builder ClearAddresses() {
        PrepareBuilder();
        result.addresses_.Clear();
        return this;
      }
    }
    static TestInteropPersonLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestInteropEmployeeIdLite : pb::GeneratedMessageLite<TestInteropEmployeeIdLite, TestInteropEmployeeIdLite.Builder> {
    private TestInteropEmployeeIdLite() { }
    private static readonly TestInteropEmployeeIdLite defaultInstance = new TestInteropEmployeeIdLite().MakeReadOnly();
    private static readonly string[] _testInteropEmployeeIdLiteFieldNames = new string[] { "number" };
    private static readonly uint[] _testInteropEmployeeIdLiteFieldTags = new uint[] { 10 };
    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) {
      CalcSerializedSize();
      string[] field_names = _testInteropEmployeeIdLiteFieldNames;
      if (hasNumber) {
        output.WriteString(1, field_names[0], Number);
      }
    }

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

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

      size = 0;
      if (hasNumber) {
        size += pb::CodedOutputStream.ComputeStringSize(1, Number);
      }
      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::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestInteropEmployeeIdLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestInteropEmployeeIdLite MakeReadOnly() {
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private TestInteropEmployeeIdLite result;

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

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

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

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

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

      public override TestInteropEmployeeIdLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestInteropEmployeeIdLite.DefaultInstance; }
      }

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

      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;
        PrepareBuilder();
        if (other.HasNumber) {
          Number = other.Number;
        }
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_testInteropEmployeeIdLiteFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _testInteropEmployeeIdLiteFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          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");
        PrepareBuilder();
        result.hasNumber = true;
        result.number_ = value;
        return this;
      }
      public Builder ClearNumber() {
        PrepareBuilder();
        result.hasNumber = false;
        result.number_ = "";
        return this;
      }
    }
    static TestInteropEmployeeIdLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestUnpackedExtensionsLite : pb::ExtendableMessageLite<TestUnpackedExtensionsLite, TestUnpackedExtensionsLite.Builder> {
    private TestUnpackedExtensionsLite() { }
    private static readonly TestUnpackedExtensionsLite defaultInstance = new TestUnpackedExtensionsLite().MakeReadOnly();
    private static readonly string[] _testUnpackedExtensionsLiteFieldNames = new string[] {  };
    private static readonly uint[] _testUnpackedExtensionsLiteFieldTags = new uint[] {  };
    public static TestUnpackedExtensionsLite DefaultInstance {
      get { return defaultInstance; }
    }

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

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

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

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _testUnpackedExtensionsLiteFieldNames;
      pb::ExtendableMessageLite<TestUnpackedExtensionsLite, TestUnpackedExtensionsLite.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);
      extensionWriter.WriteUntil(536870912, output);
    }

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

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

      size = 0;
      size += ExtensionsSerializedSize;
      memoizedSerializedSize = size;
      return size;
    }
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      hash ^= base.GetHashCode();
      return hash;
    }

    public override bool Equals(object obj) {
      TestUnpackedExtensionsLite other = obj as TestUnpackedExtensionsLite;
      if (other == null) return false;
      if (!base.Equals(other)) return false;
      return true;
    }

    public override void PrintTo(global::System.IO.TextWriter writer) {
      base.PrintTo(writer);
    }
    #endregion

    public static TestUnpackedExtensionsLite ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestUnpackedExtensionsLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestUnpackedExtensionsLite MakeReadOnly() {
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private TestUnpackedExtensionsLite result;

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

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

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

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

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

      public override TestUnpackedExtensionsLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance; }
      }

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

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

      public override Builder MergeFrom(TestUnpackedExtensionsLite other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestUnpackedExtensionsLite.DefaultInstance) return this;
        PrepareBuilder();
          this.MergeExtensionFields(other);
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_testUnpackedExtensionsLiteFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _testUnpackedExtensionsLiteFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                return this;
              }
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              break;
            }
          }
        }

        return this;
      }

    }
    static TestUnpackedExtensionsLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestUnpackedTypesLite : pb::GeneratedMessageLite<TestUnpackedTypesLite, TestUnpackedTypesLite.Builder> {
    private TestUnpackedTypesLite() { }
    private static readonly TestUnpackedTypesLite defaultInstance = new TestUnpackedTypesLite().MakeReadOnly();
    private static readonly string[] _testUnpackedTypesLiteFieldNames = new string[] { "unpacked_bool", "unpacked_double", "unpacked_enum", "unpacked_fixed32", "unpacked_fixed64", "unpacked_float", "unpacked_int32", "unpacked_int64", "unpacked_sfixed32", "unpacked_sfixed64", "unpacked_sint32", "unpacked_sint64", "unpacked_uint32", "unpacked_uint64" };
    private static readonly uint[] _testUnpackedTypesLiteFieldTags = new uint[] { 816, 809, 824, 773, 777, 805, 720, 728, 789, 793, 752, 760, 736, 744 };
    public static TestUnpackedTypesLite DefaultInstance {
      get { return defaultInstance; }
    }

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

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

    public const int UnpackedInt32FieldNumber = 90;
    private pbc::PopsicleList<int> unpackedInt32_ = new pbc::PopsicleList<int>();
    public scg::IList<int> UnpackedInt32List {
      get { return pbc::Lists.AsReadOnly(unpackedInt32_); }
    }
    public int UnpackedInt32Count {
      get { return unpackedInt32_.Count; }
    }
    public int GetUnpackedInt32(int index) {
      return unpackedInt32_[index];
    }

    public const int UnpackedInt64FieldNumber = 91;
    private pbc::PopsicleList<long> unpackedInt64_ = new pbc::PopsicleList<long>();
    public scg::IList<long> UnpackedInt64List {
      get { return pbc::Lists.AsReadOnly(unpackedInt64_); }
    }
    public int UnpackedInt64Count {
      get { return unpackedInt64_.Count; }
    }
    public long GetUnpackedInt64(int index) {
      return unpackedInt64_[index];
    }

    public const int UnpackedUint32FieldNumber = 92;
    private pbc::PopsicleList<uint> unpackedUint32_ = new pbc::PopsicleList<uint>();
    public scg::IList<uint> UnpackedUint32List {
      get { return pbc::Lists.AsReadOnly(unpackedUint32_); }
    }
    public int UnpackedUint32Count {
      get { return unpackedUint32_.Count; }
    }
    public uint GetUnpackedUint32(int index) {
      return unpackedUint32_[index];
    }

    public const int UnpackedUint64FieldNumber = 93;
    private pbc::PopsicleList<ulong> unpackedUint64_ = new pbc::PopsicleList<ulong>();
    public scg::IList<ulong> UnpackedUint64List {
      get { return pbc::Lists.AsReadOnly(unpackedUint64_); }
    }
    public int UnpackedUint64Count {
      get { return unpackedUint64_.Count; }
    }
    public ulong GetUnpackedUint64(int index) {
      return unpackedUint64_[index];
    }

    public const int UnpackedSint32FieldNumber = 94;
    private pbc::PopsicleList<int> unpackedSint32_ = new pbc::PopsicleList<int>();
    public scg::IList<int> UnpackedSint32List {
      get { return pbc::Lists.AsReadOnly(unpackedSint32_); }
    }
    public int UnpackedSint32Count {
      get { return unpackedSint32_.Count; }
    }
    public int GetUnpackedSint32(int index) {
      return unpackedSint32_[index];
    }

    public const int UnpackedSint64FieldNumber = 95;
    private pbc::PopsicleList<long> unpackedSint64_ = new pbc::PopsicleList<long>();
    public scg::IList<long> UnpackedSint64List {
      get { return pbc::Lists.AsReadOnly(unpackedSint64_); }
    }
    public int UnpackedSint64Count {
      get { return unpackedSint64_.Count; }
    }
    public long GetUnpackedSint64(int index) {
      return unpackedSint64_[index];
    }

    public const int UnpackedFixed32FieldNumber = 96;
    private pbc::PopsicleList<uint> unpackedFixed32_ = new pbc::PopsicleList<uint>();
    public scg::IList<uint> UnpackedFixed32List {
      get { return pbc::Lists.AsReadOnly(unpackedFixed32_); }
    }
    public int UnpackedFixed32Count {
      get { return unpackedFixed32_.Count; }
    }
    public uint GetUnpackedFixed32(int index) {
      return unpackedFixed32_[index];
    }

    public const int UnpackedFixed64FieldNumber = 97;
    private pbc::PopsicleList<ulong> unpackedFixed64_ = new pbc::PopsicleList<ulong>();
    public scg::IList<ulong> UnpackedFixed64List {
      get { return pbc::Lists.AsReadOnly(unpackedFixed64_); }
    }
    public int UnpackedFixed64Count {
      get { return unpackedFixed64_.Count; }
    }
    public ulong GetUnpackedFixed64(int index) {
      return unpackedFixed64_[index];
    }

    public const int UnpackedSfixed32FieldNumber = 98;
    private pbc::PopsicleList<int> unpackedSfixed32_ = new pbc::PopsicleList<int>();
    public scg::IList<int> UnpackedSfixed32List {
      get { return pbc::Lists.AsReadOnly(unpackedSfixed32_); }
    }
    public int UnpackedSfixed32Count {
      get { return unpackedSfixed32_.Count; }
    }
    public int GetUnpackedSfixed32(int index) {
      return unpackedSfixed32_[index];
    }

    public const int UnpackedSfixed64FieldNumber = 99;
    private pbc::PopsicleList<long> unpackedSfixed64_ = new pbc::PopsicleList<long>();
    public scg::IList<long> UnpackedSfixed64List {
      get { return pbc::Lists.AsReadOnly(unpackedSfixed64_); }
    }
    public int UnpackedSfixed64Count {
      get { return unpackedSfixed64_.Count; }
    }
    public long GetUnpackedSfixed64(int index) {
      return unpackedSfixed64_[index];
    }

    public const int UnpackedFloatFieldNumber = 100;
    private pbc::PopsicleList<float> unpackedFloat_ = new pbc::PopsicleList<float>();
    public scg::IList<float> UnpackedFloatList {
      get { return pbc::Lists.AsReadOnly(unpackedFloat_); }
    }
    public int UnpackedFloatCount {
      get { return unpackedFloat_.Count; }
    }
    public float GetUnpackedFloat(int index) {
      return unpackedFloat_[index];
    }

    public const int UnpackedDoubleFieldNumber = 101;
    private pbc::PopsicleList<double> unpackedDouble_ = new pbc::PopsicleList<double>();
    public scg::IList<double> UnpackedDoubleList {
      get { return pbc::Lists.AsReadOnly(unpackedDouble_); }
    }
    public int UnpackedDoubleCount {
      get { return unpackedDouble_.Count; }
    }
    public double GetUnpackedDouble(int index) {
      return unpackedDouble_[index];
    }

    public const int UnpackedBoolFieldNumber = 102;
    private pbc::PopsicleList<bool> unpackedBool_ = new pbc::PopsicleList<bool>();
    public scg::IList<bool> UnpackedBoolList {
      get { return pbc::Lists.AsReadOnly(unpackedBool_); }
    }
    public int UnpackedBoolCount {
      get { return unpackedBool_.Count; }
    }
    public bool GetUnpackedBool(int index) {
      return unpackedBool_[index];
    }

    public const int UnpackedEnumFieldNumber = 103;
    private pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite> unpackedEnum_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite>();
    public scg::IList<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite> UnpackedEnumList {
      get { return pbc::Lists.AsReadOnly(unpackedEnum_); }
    }
    public int UnpackedEnumCount {
      get { return unpackedEnum_.Count; }
    }
    public global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite GetUnpackedEnum(int index) {
      return unpackedEnum_[index];
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _testUnpackedTypesLiteFieldNames;
      if (unpackedInt32_.Count > 0) {
        output.WriteInt32Array(90, field_names[6], unpackedInt32_);
      }
      if (unpackedInt64_.Count > 0) {
        output.WriteInt64Array(91, field_names[7], unpackedInt64_);
      }
      if (unpackedUint32_.Count > 0) {
        output.WriteUInt32Array(92, field_names[12], unpackedUint32_);
      }
      if (unpackedUint64_.Count > 0) {
        output.WriteUInt64Array(93, field_names[13], unpackedUint64_);
      }
      if (unpackedSint32_.Count > 0) {
        output.WriteSInt32Array(94, field_names[10], unpackedSint32_);
      }
      if (unpackedSint64_.Count > 0) {
        output.WriteSInt64Array(95, field_names[11], unpackedSint64_);
      }
      if (unpackedFixed32_.Count > 0) {
        output.WriteFixed32Array(96, field_names[3], unpackedFixed32_);
      }
      if (unpackedFixed64_.Count > 0) {
        output.WriteFixed64Array(97, field_names[4], unpackedFixed64_);
      }
      if (unpackedSfixed32_.Count > 0) {
        output.WriteSFixed32Array(98, field_names[8], unpackedSfixed32_);
      }
      if (unpackedSfixed64_.Count > 0) {
        output.WriteSFixed64Array(99, field_names[9], unpackedSfixed64_);
      }
      if (unpackedFloat_.Count > 0) {
        output.WriteFloatArray(100, field_names[5], unpackedFloat_);
      }
      if (unpackedDouble_.Count > 0) {
        output.WriteDoubleArray(101, field_names[1], unpackedDouble_);
      }
      if (unpackedBool_.Count > 0) {
        output.WriteBoolArray(102, field_names[0], unpackedBool_);
      }
      if (unpackedEnum_.Count > 0) {
        output.WriteEnumArray(103, field_names[2], unpackedEnum_);
      }
    }

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

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

      size = 0;
      {
        int dataSize = 0;
        foreach (int element in UnpackedInt32List) {
          dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
        }
        size += dataSize;
        size += 2 * unpackedInt32_.Count;
      }
      {
        int dataSize = 0;
        foreach (long element in UnpackedInt64List) {
          dataSize += pb::CodedOutputStream.ComputeInt64SizeNoTag(element);
        }
        size += dataSize;
        size += 2 * unpackedInt64_.Count;
      }
      {
        int dataSize = 0;
        foreach (uint element in UnpackedUint32List) {
          dataSize += pb::CodedOutputStream.ComputeUInt32SizeNoTag(element);
        }
        size += dataSize;
        size += 2 * unpackedUint32_.Count;
      }
      {
        int dataSize = 0;
        foreach (ulong element in UnpackedUint64List) {
          dataSize += pb::CodedOutputStream.ComputeUInt64SizeNoTag(element);
        }
        size += dataSize;
        size += 2 * unpackedUint64_.Count;
      }
      {
        int dataSize = 0;
        foreach (int element in UnpackedSint32List) {
          dataSize += pb::CodedOutputStream.ComputeSInt32SizeNoTag(element);
        }
        size += dataSize;
        size += 2 * unpackedSint32_.Count;
      }
      {
        int dataSize = 0;
        foreach (long element in UnpackedSint64List) {
          dataSize += pb::CodedOutputStream.ComputeSInt64SizeNoTag(element);
        }
        size += dataSize;
        size += 2 * unpackedSint64_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 4 * unpackedFixed32_.Count;
        size += dataSize;
        size += 2 * unpackedFixed32_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 8 * unpackedFixed64_.Count;
        size += dataSize;
        size += 2 * unpackedFixed64_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 4 * unpackedSfixed32_.Count;
        size += dataSize;
        size += 2 * unpackedSfixed32_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 8 * unpackedSfixed64_.Count;
        size += dataSize;
        size += 2 * unpackedSfixed64_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 4 * unpackedFloat_.Count;
        size += dataSize;
        size += 2 * unpackedFloat_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 8 * unpackedDouble_.Count;
        size += dataSize;
        size += 2 * unpackedDouble_.Count;
      }
      {
        int dataSize = 0;
        dataSize = 1 * unpackedBool_.Count;
        size += dataSize;
        size += 2 * unpackedBool_.Count;
      }
      {
        int dataSize = 0;
        if (unpackedEnum_.Count > 0) {
          foreach (global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite element in unpackedEnum_) {
            dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
          }
          size += dataSize;
          size += 2 * unpackedEnum_.Count;
        }
      }
      memoizedSerializedSize = size;
      return size;
    }
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      foreach(int i in unpackedInt32_)
        hash ^= i.GetHashCode();
      foreach(long i in unpackedInt64_)
        hash ^= i.GetHashCode();
      foreach(uint i in unpackedUint32_)
        hash ^= i.GetHashCode();
      foreach(ulong i in unpackedUint64_)
        hash ^= i.GetHashCode();
      foreach(int i in unpackedSint32_)
        hash ^= i.GetHashCode();
      foreach(long i in unpackedSint64_)
        hash ^= i.GetHashCode();
      foreach(uint i in unpackedFixed32_)
        hash ^= i.GetHashCode();
      foreach(ulong i in unpackedFixed64_)
        hash ^= i.GetHashCode();
      foreach(int i in unpackedSfixed32_)
        hash ^= i.GetHashCode();
      foreach(long i in unpackedSfixed64_)
        hash ^= i.GetHashCode();
      foreach(float i in unpackedFloat_)
        hash ^= i.GetHashCode();
      foreach(double i in unpackedDouble_)
        hash ^= i.GetHashCode();
      foreach(bool i in unpackedBool_)
        hash ^= i.GetHashCode();
      foreach(global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite i in unpackedEnum_)
        hash ^= i.GetHashCode();
      return hash;
    }

    public override bool Equals(object obj) {
      TestUnpackedTypesLite other = obj as TestUnpackedTypesLite;
      if (other == null) return false;
      if(unpackedInt32_.Count != other.unpackedInt32_.Count) return false;
      for(int ix=0; ix < unpackedInt32_.Count; ix++)
        if(!unpackedInt32_[ix].Equals(other.unpackedInt32_[ix])) return false;
      if(unpackedInt64_.Count != other.unpackedInt64_.Count) return false;
      for(int ix=0; ix < unpackedInt64_.Count; ix++)
        if(!unpackedInt64_[ix].Equals(other.unpackedInt64_[ix])) return false;
      if(unpackedUint32_.Count != other.unpackedUint32_.Count) return false;
      for(int ix=0; ix < unpackedUint32_.Count; ix++)
        if(!unpackedUint32_[ix].Equals(other.unpackedUint32_[ix])) return false;
      if(unpackedUint64_.Count != other.unpackedUint64_.Count) return false;
      for(int ix=0; ix < unpackedUint64_.Count; ix++)
        if(!unpackedUint64_[ix].Equals(other.unpackedUint64_[ix])) return false;
      if(unpackedSint32_.Count != other.unpackedSint32_.Count) return false;
      for(int ix=0; ix < unpackedSint32_.Count; ix++)
        if(!unpackedSint32_[ix].Equals(other.unpackedSint32_[ix])) return false;
      if(unpackedSint64_.Count != other.unpackedSint64_.Count) return false;
      for(int ix=0; ix < unpackedSint64_.Count; ix++)
        if(!unpackedSint64_[ix].Equals(other.unpackedSint64_[ix])) return false;
      if(unpackedFixed32_.Count != other.unpackedFixed32_.Count) return false;
      for(int ix=0; ix < unpackedFixed32_.Count; ix++)
        if(!unpackedFixed32_[ix].Equals(other.unpackedFixed32_[ix])) return false;
      if(unpackedFixed64_.Count != other.unpackedFixed64_.Count) return false;
      for(int ix=0; ix < unpackedFixed64_.Count; ix++)
        if(!unpackedFixed64_[ix].Equals(other.unpackedFixed64_[ix])) return false;
      if(unpackedSfixed32_.Count != other.unpackedSfixed32_.Count) return false;
      for(int ix=0; ix < unpackedSfixed32_.Count; ix++)
        if(!unpackedSfixed32_[ix].Equals(other.unpackedSfixed32_[ix])) return false;
      if(unpackedSfixed64_.Count != other.unpackedSfixed64_.Count) return false;
      for(int ix=0; ix < unpackedSfixed64_.Count; ix++)
        if(!unpackedSfixed64_[ix].Equals(other.unpackedSfixed64_[ix])) return false;
      if(unpackedFloat_.Count != other.unpackedFloat_.Count) return false;
      for(int ix=0; ix < unpackedFloat_.Count; ix++)
        if(!unpackedFloat_[ix].Equals(other.unpackedFloat_[ix])) return false;
      if(unpackedDouble_.Count != other.unpackedDouble_.Count) return false;
      for(int ix=0; ix < unpackedDouble_.Count; ix++)
        if(!unpackedDouble_[ix].Equals(other.unpackedDouble_[ix])) return false;
      if(unpackedBool_.Count != other.unpackedBool_.Count) return false;
      for(int ix=0; ix < unpackedBool_.Count; ix++)
        if(!unpackedBool_[ix].Equals(other.unpackedBool_[ix])) return false;
      if(unpackedEnum_.Count != other.unpackedEnum_.Count) return false;
      for(int ix=0; ix < unpackedEnum_.Count; ix++)
        if(!unpackedEnum_[ix].Equals(other.unpackedEnum_[ix])) return false;
      return true;
    }

    public override void PrintTo(global::System.IO.TextWriter writer) {
      PrintField("unpacked_int32", unpackedInt32_, writer);
      PrintField("unpacked_int64", unpackedInt64_, writer);
      PrintField("unpacked_uint32", unpackedUint32_, writer);
      PrintField("unpacked_uint64", unpackedUint64_, writer);
      PrintField("unpacked_sint32", unpackedSint32_, writer);
      PrintField("unpacked_sint64", unpackedSint64_, writer);
      PrintField("unpacked_fixed32", unpackedFixed32_, writer);
      PrintField("unpacked_fixed64", unpackedFixed64_, writer);
      PrintField("unpacked_sfixed32", unpackedSfixed32_, writer);
      PrintField("unpacked_sfixed64", unpackedSfixed64_, writer);
      PrintField("unpacked_float", unpackedFloat_, writer);
      PrintField("unpacked_double", unpackedDouble_, writer);
      PrintField("unpacked_bool", unpackedBool_, writer);
      PrintField("unpacked_enum", unpackedEnum_, writer);
    }
    #endregion

    public static TestUnpackedTypesLite ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestUnpackedTypesLite ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestUnpackedTypesLite MakeReadOnly() {
      unpackedInt32_.MakeReadOnly();
      unpackedInt64_.MakeReadOnly();
      unpackedUint32_.MakeReadOnly();
      unpackedUint64_.MakeReadOnly();
      unpackedSint32_.MakeReadOnly();
      unpackedSint64_.MakeReadOnly();
      unpackedFixed32_.MakeReadOnly();
      unpackedFixed64_.MakeReadOnly();
      unpackedSfixed32_.MakeReadOnly();
      unpackedSfixed64_.MakeReadOnly();
      unpackedFloat_.MakeReadOnly();
      unpackedDouble_.MakeReadOnly();
      unpackedBool_.MakeReadOnly();
      unpackedEnum_.MakeReadOnly();
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private TestUnpackedTypesLite result;

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

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

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

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

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

      public override TestUnpackedTypesLite DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.TestUnpackedTypesLite.DefaultInstance; }
      }

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

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

      public override Builder MergeFrom(TestUnpackedTypesLite other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.TestUnpackedTypesLite.DefaultInstance) return this;
        PrepareBuilder();
        if (other.unpackedInt32_.Count != 0) {
          result.unpackedInt32_.Add(other.unpackedInt32_);
        }
        if (other.unpackedInt64_.Count != 0) {
          result.unpackedInt64_.Add(other.unpackedInt64_);
        }
        if (other.unpackedUint32_.Count != 0) {
          result.unpackedUint32_.Add(other.unpackedUint32_);
        }
        if (other.unpackedUint64_.Count != 0) {
          result.unpackedUint64_.Add(other.unpackedUint64_);
        }
        if (other.unpackedSint32_.Count != 0) {
          result.unpackedSint32_.Add(other.unpackedSint32_);
        }
        if (other.unpackedSint64_.Count != 0) {
          result.unpackedSint64_.Add(other.unpackedSint64_);
        }
        if (other.unpackedFixed32_.Count != 0) {
          result.unpackedFixed32_.Add(other.unpackedFixed32_);
        }
        if (other.unpackedFixed64_.Count != 0) {
          result.unpackedFixed64_.Add(other.unpackedFixed64_);
        }
        if (other.unpackedSfixed32_.Count != 0) {
          result.unpackedSfixed32_.Add(other.unpackedSfixed32_);
        }
        if (other.unpackedSfixed64_.Count != 0) {
          result.unpackedSfixed64_.Add(other.unpackedSfixed64_);
        }
        if (other.unpackedFloat_.Count != 0) {
          result.unpackedFloat_.Add(other.unpackedFloat_);
        }
        if (other.unpackedDouble_.Count != 0) {
          result.unpackedDouble_.Add(other.unpackedDouble_);
        }
        if (other.unpackedBool_.Count != 0) {
          result.unpackedBool_.Add(other.unpackedBool_);
        }
        if (other.unpackedEnum_.Count != 0) {
          result.unpackedEnum_.Add(other.unpackedEnum_);
        }
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_testUnpackedTypesLiteFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _testUnpackedTypesLiteFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                return this;
              }
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              break;
            }
            case 722:
            case 720: {
              input.ReadInt32Array(tag, field_name, result.unpackedInt32_);
              break;
            }
            case 730:
            case 728: {
              input.ReadInt64Array(tag, field_name, result.unpackedInt64_);
              break;
            }
            case 738:
            case 736: {
              input.ReadUInt32Array(tag, field_name, result.unpackedUint32_);
              break;
            }
            case 746:
            case 744: {
              input.ReadUInt64Array(tag, field_name, result.unpackedUint64_);
              break;
            }
            case 754:
            case 752: {
              input.ReadSInt32Array(tag, field_name, result.unpackedSint32_);
              break;
            }
            case 762:
            case 760: {
              input.ReadSInt64Array(tag, field_name, result.unpackedSint64_);
              break;
            }
            case 770:
            case 773: {
              input.ReadFixed32Array(tag, field_name, result.unpackedFixed32_);
              break;
            }
            case 778:
            case 777: {
              input.ReadFixed64Array(tag, field_name, result.unpackedFixed64_);
              break;
            }
            case 786:
            case 789: {
              input.ReadSFixed32Array(tag, field_name, result.unpackedSfixed32_);
              break;
            }
            case 794:
            case 793: {
              input.ReadSFixed64Array(tag, field_name, result.unpackedSfixed64_);
              break;
            }
            case 802:
            case 805: {
              input.ReadFloatArray(tag, field_name, result.unpackedFloat_);
              break;
            }
            case 810:
            case 809: {
              input.ReadDoubleArray(tag, field_name, result.unpackedDouble_);
              break;
            }
            case 818:
            case 816: {
              input.ReadBoolArray(tag, field_name, result.unpackedBool_);
              break;
            }
            case 826:
            case 824: {
              scg::ICollection<object> unknownItems;
              input.ReadEnumArray<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite>(tag, field_name, result.unpackedEnum_, out unknownItems);
              break;
            }
          }
        }

        return this;
      }


      public pbc::IPopsicleList<int> UnpackedInt32List {
        get { return PrepareBuilder().unpackedInt32_; }
      }
      public int UnpackedInt32Count {
        get { return result.UnpackedInt32Count; }
      }
      public int GetUnpackedInt32(int index) {
        return result.GetUnpackedInt32(index);
      }
      public Builder SetUnpackedInt32(int index, int value) {
        PrepareBuilder();
        result.unpackedInt32_[index] = value;
        return this;
      }
      public Builder AddUnpackedInt32(int value) {
        PrepareBuilder();
        result.unpackedInt32_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedInt32(scg::IEnumerable<int> values) {
        PrepareBuilder();
        result.unpackedInt32_.Add(values);
        return this;
      }
      public Builder ClearUnpackedInt32() {
        PrepareBuilder();
        result.unpackedInt32_.Clear();
        return this;
      }

      public pbc::IPopsicleList<long> UnpackedInt64List {
        get { return PrepareBuilder().unpackedInt64_; }
      }
      public int UnpackedInt64Count {
        get { return result.UnpackedInt64Count; }
      }
      public long GetUnpackedInt64(int index) {
        return result.GetUnpackedInt64(index);
      }
      public Builder SetUnpackedInt64(int index, long value) {
        PrepareBuilder();
        result.unpackedInt64_[index] = value;
        return this;
      }
      public Builder AddUnpackedInt64(long value) {
        PrepareBuilder();
        result.unpackedInt64_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedInt64(scg::IEnumerable<long> values) {
        PrepareBuilder();
        result.unpackedInt64_.Add(values);
        return this;
      }
      public Builder ClearUnpackedInt64() {
        PrepareBuilder();
        result.unpackedInt64_.Clear();
        return this;
      }

      public pbc::IPopsicleList<uint> UnpackedUint32List {
        get { return PrepareBuilder().unpackedUint32_; }
      }
      public int UnpackedUint32Count {
        get { return result.UnpackedUint32Count; }
      }
      public uint GetUnpackedUint32(int index) {
        return result.GetUnpackedUint32(index);
      }
      public Builder SetUnpackedUint32(int index, uint value) {
        PrepareBuilder();
        result.unpackedUint32_[index] = value;
        return this;
      }
      public Builder AddUnpackedUint32(uint value) {
        PrepareBuilder();
        result.unpackedUint32_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedUint32(scg::IEnumerable<uint> values) {
        PrepareBuilder();
        result.unpackedUint32_.Add(values);
        return this;
      }
      public Builder ClearUnpackedUint32() {
        PrepareBuilder();
        result.unpackedUint32_.Clear();
        return this;
      }

      public pbc::IPopsicleList<ulong> UnpackedUint64List {
        get { return PrepareBuilder().unpackedUint64_; }
      }
      public int UnpackedUint64Count {
        get { return result.UnpackedUint64Count; }
      }
      public ulong GetUnpackedUint64(int index) {
        return result.GetUnpackedUint64(index);
      }
      public Builder SetUnpackedUint64(int index, ulong value) {
        PrepareBuilder();
        result.unpackedUint64_[index] = value;
        return this;
      }
      public Builder AddUnpackedUint64(ulong value) {
        PrepareBuilder();
        result.unpackedUint64_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedUint64(scg::IEnumerable<ulong> values) {
        PrepareBuilder();
        result.unpackedUint64_.Add(values);
        return this;
      }
      public Builder ClearUnpackedUint64() {
        PrepareBuilder();
        result.unpackedUint64_.Clear();
        return this;
      }

      public pbc::IPopsicleList<int> UnpackedSint32List {
        get { return PrepareBuilder().unpackedSint32_; }
      }
      public int UnpackedSint32Count {
        get { return result.UnpackedSint32Count; }
      }
      public int GetUnpackedSint32(int index) {
        return result.GetUnpackedSint32(index);
      }
      public Builder SetUnpackedSint32(int index, int value) {
        PrepareBuilder();
        result.unpackedSint32_[index] = value;
        return this;
      }
      public Builder AddUnpackedSint32(int value) {
        PrepareBuilder();
        result.unpackedSint32_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedSint32(scg::IEnumerable<int> values) {
        PrepareBuilder();
        result.unpackedSint32_.Add(values);
        return this;
      }
      public Builder ClearUnpackedSint32() {
        PrepareBuilder();
        result.unpackedSint32_.Clear();
        return this;
      }

      public pbc::IPopsicleList<long> UnpackedSint64List {
        get { return PrepareBuilder().unpackedSint64_; }
      }
      public int UnpackedSint64Count {
        get { return result.UnpackedSint64Count; }
      }
      public long GetUnpackedSint64(int index) {
        return result.GetUnpackedSint64(index);
      }
      public Builder SetUnpackedSint64(int index, long value) {
        PrepareBuilder();
        result.unpackedSint64_[index] = value;
        return this;
      }
      public Builder AddUnpackedSint64(long value) {
        PrepareBuilder();
        result.unpackedSint64_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedSint64(scg::IEnumerable<long> values) {
        PrepareBuilder();
        result.unpackedSint64_.Add(values);
        return this;
      }
      public Builder ClearUnpackedSint64() {
        PrepareBuilder();
        result.unpackedSint64_.Clear();
        return this;
      }

      public pbc::IPopsicleList<uint> UnpackedFixed32List {
        get { return PrepareBuilder().unpackedFixed32_; }
      }
      public int UnpackedFixed32Count {
        get { return result.UnpackedFixed32Count; }
      }
      public uint GetUnpackedFixed32(int index) {
        return result.GetUnpackedFixed32(index);
      }
      public Builder SetUnpackedFixed32(int index, uint value) {
        PrepareBuilder();
        result.unpackedFixed32_[index] = value;
        return this;
      }
      public Builder AddUnpackedFixed32(uint value) {
        PrepareBuilder();
        result.unpackedFixed32_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedFixed32(scg::IEnumerable<uint> values) {
        PrepareBuilder();
        result.unpackedFixed32_.Add(values);
        return this;
      }
      public Builder ClearUnpackedFixed32() {
        PrepareBuilder();
        result.unpackedFixed32_.Clear();
        return this;
      }

      public pbc::IPopsicleList<ulong> UnpackedFixed64List {
        get { return PrepareBuilder().unpackedFixed64_; }
      }
      public int UnpackedFixed64Count {
        get { return result.UnpackedFixed64Count; }
      }
      public ulong GetUnpackedFixed64(int index) {
        return result.GetUnpackedFixed64(index);
      }
      public Builder SetUnpackedFixed64(int index, ulong value) {
        PrepareBuilder();
        result.unpackedFixed64_[index] = value;
        return this;
      }
      public Builder AddUnpackedFixed64(ulong value) {
        PrepareBuilder();
        result.unpackedFixed64_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedFixed64(scg::IEnumerable<ulong> values) {
        PrepareBuilder();
        result.unpackedFixed64_.Add(values);
        return this;
      }
      public Builder ClearUnpackedFixed64() {
        PrepareBuilder();
        result.unpackedFixed64_.Clear();
        return this;
      }

      public pbc::IPopsicleList<int> UnpackedSfixed32List {
        get { return PrepareBuilder().unpackedSfixed32_; }
      }
      public int UnpackedSfixed32Count {
        get { return result.UnpackedSfixed32Count; }
      }
      public int GetUnpackedSfixed32(int index) {
        return result.GetUnpackedSfixed32(index);
      }
      public Builder SetUnpackedSfixed32(int index, int value) {
        PrepareBuilder();
        result.unpackedSfixed32_[index] = value;
        return this;
      }
      public Builder AddUnpackedSfixed32(int value) {
        PrepareBuilder();
        result.unpackedSfixed32_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedSfixed32(scg::IEnumerable<int> values) {
        PrepareBuilder();
        result.unpackedSfixed32_.Add(values);
        return this;
      }
      public Builder ClearUnpackedSfixed32() {
        PrepareBuilder();
        result.unpackedSfixed32_.Clear();
        return this;
      }

      public pbc::IPopsicleList<long> UnpackedSfixed64List {
        get { return PrepareBuilder().unpackedSfixed64_; }
      }
      public int UnpackedSfixed64Count {
        get { return result.UnpackedSfixed64Count; }
      }
      public long GetUnpackedSfixed64(int index) {
        return result.GetUnpackedSfixed64(index);
      }
      public Builder SetUnpackedSfixed64(int index, long value) {
        PrepareBuilder();
        result.unpackedSfixed64_[index] = value;
        return this;
      }
      public Builder AddUnpackedSfixed64(long value) {
        PrepareBuilder();
        result.unpackedSfixed64_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedSfixed64(scg::IEnumerable<long> values) {
        PrepareBuilder();
        result.unpackedSfixed64_.Add(values);
        return this;
      }
      public Builder ClearUnpackedSfixed64() {
        PrepareBuilder();
        result.unpackedSfixed64_.Clear();
        return this;
      }

      public pbc::IPopsicleList<float> UnpackedFloatList {
        get { return PrepareBuilder().unpackedFloat_; }
      }
      public int UnpackedFloatCount {
        get { return result.UnpackedFloatCount; }
      }
      public float GetUnpackedFloat(int index) {
        return result.GetUnpackedFloat(index);
      }
      public Builder SetUnpackedFloat(int index, float value) {
        PrepareBuilder();
        result.unpackedFloat_[index] = value;
        return this;
      }
      public Builder AddUnpackedFloat(float value) {
        PrepareBuilder();
        result.unpackedFloat_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedFloat(scg::IEnumerable<float> values) {
        PrepareBuilder();
        result.unpackedFloat_.Add(values);
        return this;
      }
      public Builder ClearUnpackedFloat() {
        PrepareBuilder();
        result.unpackedFloat_.Clear();
        return this;
      }

      public pbc::IPopsicleList<double> UnpackedDoubleList {
        get { return PrepareBuilder().unpackedDouble_; }
      }
      public int UnpackedDoubleCount {
        get { return result.UnpackedDoubleCount; }
      }
      public double GetUnpackedDouble(int index) {
        return result.GetUnpackedDouble(index);
      }
      public Builder SetUnpackedDouble(int index, double value) {
        PrepareBuilder();
        result.unpackedDouble_[index] = value;
        return this;
      }
      public Builder AddUnpackedDouble(double value) {
        PrepareBuilder();
        result.unpackedDouble_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedDouble(scg::IEnumerable<double> values) {
        PrepareBuilder();
        result.unpackedDouble_.Add(values);
        return this;
      }
      public Builder ClearUnpackedDouble() {
        PrepareBuilder();
        result.unpackedDouble_.Clear();
        return this;
      }

      public pbc::IPopsicleList<bool> UnpackedBoolList {
        get { return PrepareBuilder().unpackedBool_; }
      }
      public int UnpackedBoolCount {
        get { return result.UnpackedBoolCount; }
      }
      public bool GetUnpackedBool(int index) {
        return result.GetUnpackedBool(index);
      }
      public Builder SetUnpackedBool(int index, bool value) {
        PrepareBuilder();
        result.unpackedBool_[index] = value;
        return this;
      }
      public Builder AddUnpackedBool(bool value) {
        PrepareBuilder();
        result.unpackedBool_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedBool(scg::IEnumerable<bool> values) {
        PrepareBuilder();
        result.unpackedBool_.Add(values);
        return this;
      }
      public Builder ClearUnpackedBool() {
        PrepareBuilder();
        result.unpackedBool_.Clear();
        return this;
      }

      public pbc::IPopsicleList<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite> UnpackedEnumList {
        get { return PrepareBuilder().unpackedEnum_; }
      }
      public int UnpackedEnumCount {
        get { return result.UnpackedEnumCount; }
      }
      public global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite GetUnpackedEnum(int index) {
        return result.GetUnpackedEnum(index);
      }
      public Builder SetUnpackedEnum(int index, global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite value) {
        PrepareBuilder();
        result.unpackedEnum_[index] = value;
        return this;
      }
      public Builder AddUnpackedEnum(global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite value) {
        PrepareBuilder();
        result.unpackedEnum_.Add(value);
        return this;
      }
      public Builder AddRangeUnpackedEnum(scg::IEnumerable<global::Google.ProtocolBuffers.TestProtos.UnpackedTypesForeignEnumLite> values) {
        PrepareBuilder();
        result.unpackedEnum_.Add(values);
        return this;
      }
      public Builder ClearUnpackedEnum() {
        PrepareBuilder();
        result.unpackedEnum_.Clear();
        return this;
      }
    }
    static TestUnpackedTypesLite() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class BucketOfBytes : pb::GeneratedMessageLite<BucketOfBytes, BucketOfBytes.Builder> {
    private BucketOfBytes() { }
    private static readonly BucketOfBytes defaultInstance = new BucketOfBytes().MakeReadOnly();
    private static readonly string[] _bucketOfBytesFieldNames = new string[] { "value" };
    private static readonly uint[] _bucketOfBytesFieldTags = new uint[] { 10 };
    public static BucketOfBytes DefaultInstance {
      get { return defaultInstance; }
    }

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

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

    public const int ValueFieldNumber = 1;
    private bool hasValue;
    private pb::ByteString value_ = pb::ByteString.Empty;
    public bool HasValue {
      get { return hasValue; }
    }
    public pb::ByteString Value {
      get { return value_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _bucketOfBytesFieldNames;
      if (hasValue) {
        output.WriteBytes(1, field_names[0], Value);
      }
    }

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

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

      size = 0;
      if (hasValue) {
        size += pb::CodedOutputStream.ComputeBytesSize(1, Value);
      }
      memoizedSerializedSize = size;
      return size;
    }
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      if (hasValue) {
        hash ^= value_.GetHashCode();
      }
      return hash;
    }

    public override bool Equals(object obj) {
      BucketOfBytes other = obj as BucketOfBytes;
      if (other == null) return false;
      if (hasValue != other.hasValue || (hasValue && !value_.Equals(other.value_))) return false;
      return true;
    }

    public override void PrintTo(global::System.IO.TextWriter writer) {
      PrintField("value", hasValue, value_, writer);
    }
    #endregion

    public static BucketOfBytes ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static BucketOfBytes ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static BucketOfBytes ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static BucketOfBytes ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private BucketOfBytes MakeReadOnly() {
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private BucketOfBytes result;

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

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

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

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

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

      public override BucketOfBytes DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.BucketOfBytes.DefaultInstance; }
      }

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

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

      public override Builder MergeFrom(BucketOfBytes other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.BucketOfBytes.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasValue) {
          Value = other.Value;
        }
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_bucketOfBytesFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _bucketOfBytesFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          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.hasValue = input.ReadBytes(ref result.value_);
              break;
            }
          }
        }

        return this;
      }


      public bool HasValue {
        get { return result.hasValue; }
      }
      public pb::ByteString Value {
        get { return result.Value; }
        set { SetValue(value); }
      }
      public Builder SetValue(pb::ByteString value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasValue = true;
        result.value_ = value;
        return this;
      }
      public Builder ClearValue() {
        PrepareBuilder();
        result.hasValue = false;
        result.value_ = pb::ByteString.Empty;
        return this;
      }
    }
    static BucketOfBytes() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class BucketOfBytesEx : pb::GeneratedMessageLite<BucketOfBytesEx, BucketOfBytesEx.Builder> {
    private BucketOfBytesEx() { }
    private static readonly BucketOfBytesEx defaultInstance = new BucketOfBytesEx().MakeReadOnly();
    private static readonly string[] _bucketOfBytesExFieldNames = new string[] { "value", "value2" };
    private static readonly uint[] _bucketOfBytesExFieldTags = new uint[] { 10, 2042 };
    public static BucketOfBytesEx DefaultInstance {
      get { return defaultInstance; }
    }

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

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

    public const int ValueFieldNumber = 1;
    private bool hasValue;
    private pb::ByteString value_ = pb::ByteString.Empty;
    public bool HasValue {
      get { return hasValue; }
    }
    public pb::ByteString Value {
      get { return value_; }
    }

    public const int Value2FieldNumber = 255;
    private bool hasValue2;
    private pb::ByteString value2_ = pb::ByteString.Empty;
    public bool HasValue2 {
      get { return hasValue2; }
    }
    public pb::ByteString Value2 {
      get { return value2_; }
    }

    public override bool IsInitialized {
      get {
        return true;
      }
    }

    public override void WriteTo(pb::ICodedOutputStream output) {
      CalcSerializedSize();
      string[] field_names = _bucketOfBytesExFieldNames;
      if (hasValue) {
        output.WriteBytes(1, field_names[0], Value);
      }
      if (hasValue2) {
        output.WriteBytes(255, field_names[1], Value2);
      }
    }

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

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

      size = 0;
      if (hasValue) {
        size += pb::CodedOutputStream.ComputeBytesSize(1, Value);
      }
      if (hasValue2) {
        size += pb::CodedOutputStream.ComputeBytesSize(255, Value2);
      }
      memoizedSerializedSize = size;
      return size;
    }
    #region Lite runtime methods
    public override int GetHashCode() {
      int hash = GetType().GetHashCode();
      if (hasValue) {
        hash ^= value_.GetHashCode();
      }
      if (hasValue2) {
        hash ^= value2_.GetHashCode();
      }
      return hash;
    }

    public override bool Equals(object obj) {
      BucketOfBytesEx other = obj as BucketOfBytesEx;
      if (other == null) return false;
      if (hasValue != other.hasValue || (hasValue && !value_.Equals(other.value_))) return false;
      if (hasValue2 != other.hasValue2 || (hasValue2 && !value2_.Equals(other.value2_))) return false;
      return true;
    }

    public override void PrintTo(global::System.IO.TextWriter writer) {
      PrintField("value", hasValue, value_, writer);
      PrintField("value2", hasValue2, value2_, writer);
    }
    #endregion

    public static BucketOfBytesEx ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static BucketOfBytesEx ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static BucketOfBytesEx ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static BucketOfBytesEx ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private BucketOfBytesEx MakeReadOnly() {
      return this;
    }

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

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

      private bool resultIsReadOnly;
      private BucketOfBytesEx result;

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

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

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

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

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

      public override BucketOfBytesEx DefaultInstanceForType {
        get { return global::Google.ProtocolBuffers.TestProtos.BucketOfBytesEx.DefaultInstance; }
      }

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

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

      public override Builder MergeFrom(BucketOfBytesEx other) {
        if (other == global::Google.ProtocolBuffers.TestProtos.BucketOfBytesEx.DefaultInstance) return this;
        PrepareBuilder();
        if (other.HasValue) {
          Value = other.Value;
        }
        if (other.HasValue2) {
          Value2 = other.Value2;
        }
        return this;
      }

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

      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        PrepareBuilder();
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_bucketOfBytesExFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _bucketOfBytesExFieldTags[field_ordinal];
            else {
              ParseUnknownField(input, extensionRegistry, tag, field_name);
              continue;
            }
          }
          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.hasValue = input.ReadBytes(ref result.value_);
              break;
            }
            case 2042: {
              result.hasValue2 = input.ReadBytes(ref result.value2_);
              break;
            }
          }
        }

        return this;
      }


      public bool HasValue {
        get { return result.hasValue; }
      }
      public pb::ByteString Value {
        get { return result.Value; }
        set { SetValue(value); }
      }
      public Builder SetValue(pb::ByteString value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasValue = true;
        result.value_ = value;
        return this;
      }
      public Builder ClearValue() {
        PrepareBuilder();
        result.hasValue = false;
        result.value_ = pb::ByteString.Empty;
        return this;
      }

      public bool HasValue2 {
        get { return result.hasValue2; }
      }
      public pb::ByteString Value2 {
        get { return result.Value2; }
        set { SetValue2(value); }
      }
      public Builder SetValue2(pb::ByteString value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasValue2 = true;
        result.value2_ = value;
        return this;
      }
      public Builder ClearValue2() {
        PrepareBuilder();
        result.hasValue2 = false;
        result.value2_ = pb::ByteString.Empty;
        return this;
      }
    }
    static BucketOfBytesEx() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestExtrasLite.Descriptor, null);
    }
  }

  #endregion

}

#endregion Designer generated code
