// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/protobuf/unittest_optimize_for.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 UnittestOptimizeFor {

    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
      registry.Add(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.TestExtension);
      registry.Add(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.TestExtension2);
    }
    #endregion
    #region Static variables
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder> internal__static_protobuf_unittest_TestOptimizedForSize__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder> internal__static_protobuf_unittest_TestRequiredOptimizedForSize__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize.Builder> internal__static_protobuf_unittest_TestOptionalOptimizedForSize__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;

    static UnittestOptimizeFor() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "Citnb29nbGUvcHJvdG9idWYvdW5pdHRlc3Rfb3B0aW1pemVfZm9yLnByb3Rv", 
            "EhFwcm90b2J1Zl91bml0dGVzdBoeZ29vZ2xlL3Byb3RvYnVmL3VuaXR0ZXN0", 
            "LnByb3RvIsoCChRUZXN0T3B0aW1pemVkRm9yU2l6ZRIJCgFpGAEgASgFEi4K", 
            "A21zZxgTIAEoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdl", 
            "EhcKDWludGVnZXJfZmllbGQYAiABKAVIABIWCgxzdHJpbmdfZmllbGQYAyAB", 
            "KAlIACoJCOgHEICAgIACMkAKDnRlc3RfZXh0ZW5zaW9uEicucHJvdG9idWZf", 
            "dW5pdHRlc3QuVGVzdE9wdGltaXplZEZvclNpemUY0gkgASgFMnIKD3Rlc3Rf", 
            "ZXh0ZW5zaW9uMhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPcHRpbWl6ZWRG", 
            "b3JTaXplGNMJIAEoCzIvLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJl", 
            "ZE9wdGltaXplZEZvclNpemVCBQoDZm9vIikKHFRlc3RSZXF1aXJlZE9wdGlt", 
            "aXplZEZvclNpemUSCQoBeBgBIAIoBSJaChxUZXN0T3B0aW9uYWxPcHRpbWl6", 
            "ZWRGb3JTaXplEjoKAW8YASABKAsyLy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", 
            "UmVxdWlyZWRPcHRpbWl6ZWRGb3JTaXplQiZIAqoCIUdvb2dsZS5Qcm90b2Nv", 
          "bEJ1ZmZlcnMuVGVzdFByb3Rvcw=="));
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor = Descriptor.MessageTypes[0];
        internal__static_protobuf_unittest_TestOptimizedForSize__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor,
                new string[] { "I", "Msg", "IntegerField", "StringField", });
        global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.TestExtension = pb::GeneratedSingleExtension<int>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Descriptor.Extensions[0]);
        global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.TestExtension2 = pb::GeneratedSingleExtension<global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize>.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Descriptor.Extensions[1]);
        internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor = Descriptor.MessageTypes[1];
        internal__static_protobuf_unittest_TestRequiredOptimizedForSize__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor,
                new string[] { "X", });
        internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor = Descriptor.MessageTypes[2];
        internal__static_protobuf_unittest_TestOptionalOptimizedForSize__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize, global::Google.ProtocolBuffers.TestProtos.TestOptionalOptimizedForSize.Builder>(internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor,
                new string[] { "O", });
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.TestProtos.Unittest.RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, 
          }, assigner);
    }
    #endregion

  }
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  public sealed partial class TestOptimizedForSize : pb::ExtendableMessage<TestOptimizedForSize, TestOptimizedForSize.Builder> {
    private TestOptimizedForSize() { }
    private static readonly TestOptimizedForSize defaultInstance = new TestOptimizedForSize().MakeReadOnly();
    public static TestOptimizedForSize DefaultInstance {
      get { return defaultInstance; }
    }

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

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

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<TestOptimizedForSize, TestOptimizedForSize.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.internal__static_protobuf_unittest_TestOptimizedForSize__FieldAccessorTable; }
    }

    public const int TestExtensionFieldNumber = 1234;
    public static pb::GeneratedExtensionBase<int> TestExtension;
    public const int TestExtension2FieldNumber = 1235;
    public static pb::GeneratedExtensionBase<global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize> TestExtension2;
    public const int IFieldNumber = 1;
    private bool hasI;
    private int i_;
    public bool HasI {
      get { return hasI; }
    }
    public int I {
      get { return i_; }
    }

    public const int MsgFieldNumber = 19;
    private bool hasMsg;
    private global::Google.ProtocolBuffers.TestProtos.ForeignMessage msg_;
    public bool HasMsg {
      get { return hasMsg; }
    }
    public global::Google.ProtocolBuffers.TestProtos.ForeignMessage Msg {
      get { return msg_ ?? global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance; }
    }

    public const int IntegerFieldFieldNumber = 2;
    private bool hasIntegerField;
    private int integerField_;
    public bool HasIntegerField {
      get { return hasIntegerField; }
    }
    public int IntegerField {
      get { return integerField_; }
    }

    public const int StringFieldFieldNumber = 3;
    private bool hasStringField;
    private string stringField_ = "";
    public bool HasStringField {
      get { return hasStringField; }
    }
    public string StringField {
      get { return stringField_; }
    }

    public static TestOptimizedForSize ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestOptimizedForSize 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(TestOptimizedForSize prototype) {
      return new Builder(prototype);
    }

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

      private bool resultIsReadOnly;
      private TestOptimizedForSize result;

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

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

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

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

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

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

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

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


      public bool HasI {
        get { return result.hasI; }
      }
      public int I {
        get { return result.I; }
        set { SetI(value); }
      }
      public Builder SetI(int value) {
        PrepareBuilder();
        result.hasI = true;
        result.i_ = value;
        return this;
      }
      public Builder ClearI() {
        PrepareBuilder();
        result.hasI = false;
        result.i_ = 0;
        return this;
      }

      public bool HasMsg {
       get { return result.hasMsg; }
      }
      public global::Google.ProtocolBuffers.TestProtos.ForeignMessage Msg {
        get { return result.Msg; }
        set { SetMsg(value); }
      }
      public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasMsg = true;
        result.msg_ = value;
        return this;
      }
      public Builder SetMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasMsg = true;
        result.msg_ = builderForValue.Build();
        return this;
      }
      public Builder MergeMsg(global::Google.ProtocolBuffers.TestProtos.ForeignMessage value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasMsg &&
            result.msg_ != global::Google.ProtocolBuffers.TestProtos.ForeignMessage.DefaultInstance) {
            result.msg_ = global::Google.ProtocolBuffers.TestProtos.ForeignMessage.CreateBuilder(result.msg_).MergeFrom(value).BuildPartial();
        } else {
          result.msg_ = value;
        }
        result.hasMsg = true;
        return this;
      }
      public Builder ClearMsg() {
        PrepareBuilder();
        result.hasMsg = false;
        result.msg_ = null;
        return this;
      }

      public bool HasIntegerField {
        get { return result.hasIntegerField; }
      }
      public int IntegerField {
        get { return result.IntegerField; }
        set { SetIntegerField(value); }
      }
      public Builder SetIntegerField(int value) {
        PrepareBuilder();
        result.hasIntegerField = true;
        result.integerField_ = value;
        return this;
      }
      public Builder ClearIntegerField() {
        PrepareBuilder();
        result.hasIntegerField = false;
        result.integerField_ = 0;
        return this;
      }

      public bool HasStringField {
        get { return result.hasStringField; }
      }
      public string StringField {
        get { return result.StringField; }
        set { SetStringField(value); }
      }
      public Builder SetStringField(string value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasStringField = true;
        result.stringField_ = value;
        return this;
      }
      public Builder ClearStringField() {
        PrepareBuilder();
        result.hasStringField = false;
        result.stringField_ = "";
        return this;
      }
    }
    static TestOptimizedForSize() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.Descriptor, null);
    }
  }

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

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

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

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<TestRequiredOptimizedForSize, TestRequiredOptimizedForSize.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.internal__static_protobuf_unittest_TestRequiredOptimizedForSize__FieldAccessorTable; }
    }

    public const int XFieldNumber = 1;
    private bool hasX;
    private int x_;
    public bool HasX {
      get { return hasX; }
    }
    public int X {
      get { return x_; }
    }

    public static TestRequiredOptimizedForSize ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestRequiredOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestRequiredOptimizedForSize 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(TestRequiredOptimizedForSize prototype) {
      return new Builder(prototype);
    }

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

      private bool resultIsReadOnly;
      private TestRequiredOptimizedForSize result;

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

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

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

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

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

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

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

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


      public bool HasX {
        get { return result.hasX; }
      }
      public int X {
        get { return result.X; }
        set { SetX(value); }
      }
      public Builder SetX(int value) {
        PrepareBuilder();
        result.hasX = true;
        result.x_ = value;
        return this;
      }
      public Builder ClearX() {
        PrepareBuilder();
        result.hasX = false;
        result.x_ = 0;
        return this;
      }
    }
    static TestRequiredOptimizedForSize() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.Descriptor, null);
    }
  }

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

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

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

    public static pbd::MessageDescriptor Descriptor {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.internal__static_protobuf_unittest_TestOptionalOptimizedForSize__Descriptor; }
    }

    protected override pb::FieldAccess.FieldAccessorTable<TestOptionalOptimizedForSize, TestOptionalOptimizedForSize.Builder> InternalFieldAccessors {
      get { return global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.internal__static_protobuf_unittest_TestOptionalOptimizedForSize__FieldAccessorTable; }
    }

    public const int OFieldNumber = 1;
    private bool hasO;
    private global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize o_;
    public bool HasO {
      get { return hasO; }
    }
    public global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize O {
      get { return o_ ?? global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance; }
    }

    public static TestOptionalOptimizedForSize ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static TestOptionalOptimizedForSize ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    private TestOptionalOptimizedForSize 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(TestOptionalOptimizedForSize prototype) {
      return new Builder(prototype);
    }

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

      private bool resultIsReadOnly;
      private TestOptionalOptimizedForSize result;

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

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

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

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

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

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

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

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


      public bool HasO {
       get { return result.hasO; }
      }
      public global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize O {
        get { return result.O; }
        set { SetO(value); }
      }
      public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        result.hasO = true;
        result.o_ = value;
        return this;
      }
      public Builder SetO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        PrepareBuilder();
        result.hasO = true;
        result.o_ = builderForValue.Build();
        return this;
      }
      public Builder MergeO(global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        PrepareBuilder();
        if (result.hasO &&
            result.o_ != global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.DefaultInstance) {
            result.o_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOptimizedForSize.CreateBuilder(result.o_).MergeFrom(value).BuildPartial();
        } else {
          result.o_ = value;
        }
        result.hasO = true;
        return this;
      }
      public Builder ClearO() {
        PrepareBuilder();
        result.hasO = false;
        result.o_ = null;
        return this;
      }
    }
    static TestOptionalOptimizedForSize() {
      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnittestOptimizeFor.Descriptor, null);
    }
  }

  #endregion

}

#endregion Designer generated code
