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

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Conformance {

  /// <summary>Holder for reflection information generated from conformance.proto</summary>
  public static partial class ConformanceReflection {

    #region Descriptor
    /// <summary>File descriptor for conformance.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static ConformanceReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiHQoKRmFpbHVyZVNl",
            "dBIPCgdmYWlsdXJlGAEgAygJIuMCChJDb25mb3JtYW5jZVJlcXVlc3QSGgoQ",
            "cHJvdG9idWZfcGF5bG9hZBgBIAEoDEgAEhYKDGpzb25fcGF5bG9hZBgCIAEo",
            "CUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRleHRfcGF5bG9hZBgI",
            "IAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRwdXRfZm9ybWF0GAMgASgOMhcuY29u",
            "Zm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxtZXNzYWdlX3R5cGUYBCABKAkSMAoN",
            "dGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNvbmZvcm1hbmNlLlRlc3RDYXRlZ29y",
            "eRI+ChVqc3BiX2VuY29kaW5nX29wdGlvbnMYBiABKAsyHy5jb25mb3JtYW5j",
            "ZS5Kc3BiRW5jb2RpbmdDb25maWcSHAoUcHJpbnRfdW5rbm93bl9maWVsZHMY",
            "CSABKAhCCQoHcGF5bG9hZCLhAQoTQ29uZm9ybWFuY2VSZXNwb25zZRIVCgtw",
            "YXJzZV9lcnJvchgBIAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEoCUgA",
            "EhcKDXJ1bnRpbWVfZXJyb3IYAiABKAlIABIaChBwcm90b2J1Zl9wYXlsb2Fk",
            "GAMgASgMSAASFgoManNvbl9wYXlsb2FkGAQgASgJSAASEQoHc2tpcHBlZBgF",
            "IAEoCUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRleHRfcGF5bG9h",
            "ZBgIIAEoCUgAQggKBnJlc3VsdCI3ChJKc3BiRW5jb2RpbmdDb25maWcSIQoZ",
            "dXNlX2pzcGJfYXJyYXlfYW55X2Zvcm1hdBgBIAEoCCpQCgpXaXJlRm9ybWF0",
            "Eg8KC1VOU1BFQ0lGSUVEEAASDAoIUFJPVE9CVUYQARIICgRKU09OEAISCAoE",
            "SlNQQhADEg8KC1RFWFRfRk9STUFUEAQqjwEKDFRlc3RDYXRlZ29yeRIUChBV",
            "TlNQRUNJRklFRF9URVNUEAASDwoLQklOQVJZX1RFU1QQARINCglKU09OX1RF",
            "U1QQAhIkCiBKU09OX0lHTk9SRV9VTktOT1dOX1BBUlNJTkdfVEVTVBADEg0K",
            "CUpTUEJfVEVTVBAEEhQKEFRFWFRfRk9STUFUX1RFU1QQBUIhCh9jb20uZ29v",
            "Z2xlLnByb3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90bzM="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Failure" }, null, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "TextPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions", "PrintUnknownFields" }, new[]{ "Payload" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload", "TextPayload" }, new[]{ "Result" }, null, null, null),
            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.JspbEncodingConfig), global::Conformance.JspbEncodingConfig.Parser, new[]{ "UseJspbArrayAnyFormat" }, null, null, null, null)
          }));
    }
    #endregion

  }
  #region Enums
  public enum WireFormat {
    [pbr::OriginalName("UNSPECIFIED")] Unspecified = 0,
    [pbr::OriginalName("PROTOBUF")] Protobuf = 1,
    [pbr::OriginalName("JSON")] Json = 2,
    /// <summary>
    /// Google internal only. Opensource testees just skip it.
    /// </summary>
    [pbr::OriginalName("JSPB")] Jspb = 3,
    [pbr::OriginalName("TEXT_FORMAT")] TextFormat = 4,
  }

  public enum TestCategory {
    [pbr::OriginalName("UNSPECIFIED_TEST")] UnspecifiedTest = 0,
    /// <summary>
    /// Test binary wire format.
    /// </summary>
    [pbr::OriginalName("BINARY_TEST")] BinaryTest = 1,
    /// <summary>
    /// Test json wire format.
    /// </summary>
    [pbr::OriginalName("JSON_TEST")] JsonTest = 2,
    /// <summary>
    /// Similar to JSON_TEST. However, during parsing json, testee should ignore
    /// unknown fields. This feature is optional. Each implementation can descide
    /// whether to support it.  See
    /// https://developers.google.com/protocol-buffers/docs/proto3#json_options
    /// for more detail.
    /// </summary>
    [pbr::OriginalName("JSON_IGNORE_UNKNOWN_PARSING_TEST")] JsonIgnoreUnknownParsingTest = 3,
    /// <summary>
    /// Test jspb wire format. Google internal only. Opensource testees just skip it.
    /// </summary>
    [pbr::OriginalName("JSPB_TEST")] JspbTest = 4,
    /// <summary>
    /// Test text format. For cpp, java and python, testees can already deal with
    /// this type. Testees of other languages can simply skip it.
    /// </summary>
    [pbr::OriginalName("TEXT_FORMAT_TEST")] TextFormatTest = 5,
  }

  #endregion

  #region Messages
  /// <summary>
  /// The conformance runner will request a list of failures as the first request.
  /// This will be known by message_type == "conformance.FailureSet", a conformance
  /// test should return a serialized FailureSet in protobuf_payload.
  /// </summary>
  public sealed partial class FailureSet : pb::IMessage<FailureSet> {
    private static readonly pb::MessageParser<FailureSet> _parser = new pb::MessageParser<FailureSet>(() => new FailureSet());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<FailureSet> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public FailureSet() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public FailureSet(FailureSet other) : this() {
      failure_ = other.failure_.Clone();
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public FailureSet Clone() {
      return new FailureSet(this);
    }

    /// <summary>Field number for the "failure" field.</summary>
    public const int FailureFieldNumber = 1;
    private static readonly pb::FieldCodec<string> _repeated_failure_codec
        = pb::FieldCodec.ForString(10);
    private readonly pbc::RepeatedField<string> failure_ = new pbc::RepeatedField<string>();
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pbc::RepeatedField<string> Failure {
      get { return failure_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as FailureSet);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(FailureSet other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if(!failure_.Equals(other.failure_)) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      hash ^= failure_.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      failure_.WriteTo(output, _repeated_failure_codec);
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      size += failure_.CalculateSize(_repeated_failure_codec);
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(FailureSet other) {
      if (other == null) {
        return;
      }
      failure_.Add(other.failure_);
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            failure_.AddEntriesFrom(input, _repeated_failure_codec);
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Represents a single test case's input.  The testee should:
  ///
  ///   1. parse this proto (which should always succeed)
  ///   2. parse the protobuf or JSON payload in "payload" (which may fail)
  ///   3. if the parse succeeded, serialize the message in the requested format.
  /// </summary>
  public sealed partial class ConformanceRequest : pb::IMessage<ConformanceRequest> {
    private static readonly pb::MessageParser<ConformanceRequest> _parser = new pb::MessageParser<ConformanceRequest>(() => new ConformanceRequest());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ConformanceRequest> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ConformanceRequest() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ConformanceRequest(ConformanceRequest other) : this() {
      requestedOutputFormat_ = other.requestedOutputFormat_;
      messageType_ = other.messageType_;
      testCategory_ = other.testCategory_;
      jspbEncodingOptions_ = other.jspbEncodingOptions_ != null ? other.jspbEncodingOptions_.Clone() : null;
      printUnknownFields_ = other.printUnknownFields_;
      switch (other.PayloadCase) {
        case PayloadOneofCase.ProtobufPayload:
          ProtobufPayload = other.ProtobufPayload;
          break;
        case PayloadOneofCase.JsonPayload:
          JsonPayload = other.JsonPayload;
          break;
        case PayloadOneofCase.JspbPayload:
          JspbPayload = other.JspbPayload;
          break;
        case PayloadOneofCase.TextPayload:
          TextPayload = other.TextPayload;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ConformanceRequest Clone() {
      return new ConformanceRequest(this);
    }

    /// <summary>Field number for the "protobuf_payload" field.</summary>
    public const int ProtobufPayloadFieldNumber = 1;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString ProtobufPayload {
      get { return payloadCase_ == PayloadOneofCase.ProtobufPayload ? (pb::ByteString) payload_ : pb::ByteString.Empty; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        payloadCase_ = PayloadOneofCase.ProtobufPayload;
      }
    }

    /// <summary>Field number for the "json_payload" field.</summary>
    public const int JsonPayloadFieldNumber = 2;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string JsonPayload {
      get { return payloadCase_ == PayloadOneofCase.JsonPayload ? (string) payload_ : ""; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        payloadCase_ = PayloadOneofCase.JsonPayload;
      }
    }

    /// <summary>Field number for the "jspb_payload" field.</summary>
    public const int JspbPayloadFieldNumber = 7;
    /// <summary>
    /// Google internal only.  Opensource testees just skip it.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string JspbPayload {
      get { return payloadCase_ == PayloadOneofCase.JspbPayload ? (string) payload_ : ""; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        payloadCase_ = PayloadOneofCase.JspbPayload;
      }
    }

    /// <summary>Field number for the "text_payload" field.</summary>
    public const int TextPayloadFieldNumber = 8;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string TextPayload {
      get { return payloadCase_ == PayloadOneofCase.TextPayload ? (string) payload_ : ""; }
      set {
        payload_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        payloadCase_ = PayloadOneofCase.TextPayload;
      }
    }

    /// <summary>Field number for the "requested_output_format" field.</summary>
    public const int RequestedOutputFormatFieldNumber = 3;
    private global::Conformance.WireFormat requestedOutputFormat_ = global::Conformance.WireFormat.Unspecified;
    /// <summary>
    /// Which format should the testee serialize its message to?
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Conformance.WireFormat RequestedOutputFormat {
      get { return requestedOutputFormat_; }
      set {
        requestedOutputFormat_ = value;
      }
    }

    /// <summary>Field number for the "message_type" field.</summary>
    public const int MessageTypeFieldNumber = 4;
    private string messageType_ = "";
    /// <summary>
    /// The full name for the test message to use; for the moment, either:
    /// protobuf_test_messages.proto3.TestAllTypesProto3 or
    /// protobuf_test_messages.proto2.TestAllTypesProto2.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string MessageType {
      get { return messageType_; }
      set {
        messageType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "test_category" field.</summary>
    public const int TestCategoryFieldNumber = 5;
    private global::Conformance.TestCategory testCategory_ = global::Conformance.TestCategory.UnspecifiedTest;
    /// <summary>
    /// Each test is given a specific test category. Some category may need
    /// spedific support in testee programs. Refer to the defintion of TestCategory
    /// for more information.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Conformance.TestCategory TestCategory {
      get { return testCategory_; }
      set {
        testCategory_ = value;
      }
    }

    /// <summary>Field number for the "jspb_encoding_options" field.</summary>
    public const int JspbEncodingOptionsFieldNumber = 6;
    private global::Conformance.JspbEncodingConfig jspbEncodingOptions_;
    /// <summary>
    /// Specify details for how to encode jspb.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public global::Conformance.JspbEncodingConfig JspbEncodingOptions {
      get { return jspbEncodingOptions_; }
      set {
        jspbEncodingOptions_ = value;
      }
    }

    /// <summary>Field number for the "print_unknown_fields" field.</summary>
    public const int PrintUnknownFieldsFieldNumber = 9;
    private bool printUnknownFields_;
    /// <summary>
    /// This can be used in json and text format. If true, testee should print
    /// unknown fields instead of ignore. This feature is optional.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool PrintUnknownFields {
      get { return printUnknownFields_; }
      set {
        printUnknownFields_ = value;
      }
    }

    private object payload_;
    /// <summary>Enum of possible cases for the "payload" oneof.</summary>
    public enum PayloadOneofCase {
      None = 0,
      ProtobufPayload = 1,
      JsonPayload = 2,
      JspbPayload = 7,
      TextPayload = 8,
    }
    private PayloadOneofCase payloadCase_ = PayloadOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public PayloadOneofCase PayloadCase {
      get { return payloadCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearPayload() {
      payloadCase_ = PayloadOneofCase.None;
      payload_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ConformanceRequest);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ConformanceRequest other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ProtobufPayload != other.ProtobufPayload) return false;
      if (JsonPayload != other.JsonPayload) return false;
      if (JspbPayload != other.JspbPayload) return false;
      if (TextPayload != other.TextPayload) return false;
      if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
      if (MessageType != other.MessageType) return false;
      if (TestCategory != other.TestCategory) return false;
      if (!object.Equals(JspbEncodingOptions, other.JspbEncodingOptions)) return false;
      if (PrintUnknownFields != other.PrintUnknownFields) return false;
      if (PayloadCase != other.PayloadCase) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
      if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
      if (payloadCase_ == PayloadOneofCase.JspbPayload) hash ^= JspbPayload.GetHashCode();
      if (payloadCase_ == PayloadOneofCase.TextPayload) hash ^= TextPayload.GetHashCode();
      if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) hash ^= RequestedOutputFormat.GetHashCode();
      if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
      if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) hash ^= TestCategory.GetHashCode();
      if (jspbEncodingOptions_ != null) hash ^= JspbEncodingOptions.GetHashCode();
      if (PrintUnknownFields != false) hash ^= PrintUnknownFields.GetHashCode();
      hash ^= (int) payloadCase_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
        output.WriteRawTag(10);
        output.WriteBytes(ProtobufPayload);
      }
      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
        output.WriteRawTag(18);
        output.WriteString(JsonPayload);
      }
      if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) {
        output.WriteRawTag(24);
        output.WriteEnum((int) RequestedOutputFormat);
      }
      if (MessageType.Length != 0) {
        output.WriteRawTag(34);
        output.WriteString(MessageType);
      }
      if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) {
        output.WriteRawTag(40);
        output.WriteEnum((int) TestCategory);
      }
      if (jspbEncodingOptions_ != null) {
        output.WriteRawTag(50);
        output.WriteMessage(JspbEncodingOptions);
      }
      if (payloadCase_ == PayloadOneofCase.JspbPayload) {
        output.WriteRawTag(58);
        output.WriteString(JspbPayload);
      }
      if (payloadCase_ == PayloadOneofCase.TextPayload) {
        output.WriteRawTag(66);
        output.WriteString(TextPayload);
      }
      if (PrintUnknownFields != false) {
        output.WriteRawTag(72);
        output.WriteBool(PrintUnknownFields);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (payloadCase_ == PayloadOneofCase.ProtobufPayload) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload);
      }
      if (payloadCase_ == PayloadOneofCase.JsonPayload) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload);
      }
      if (payloadCase_ == PayloadOneofCase.JspbPayload) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JspbPayload);
      }
      if (payloadCase_ == PayloadOneofCase.TextPayload) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(TextPayload);
      }
      if (RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat);
      }
      if (MessageType.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType);
      }
      if (TestCategory != global::Conformance.TestCategory.UnspecifiedTest) {
        size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) TestCategory);
      }
      if (jspbEncodingOptions_ != null) {
        size += 1 + pb::CodedOutputStream.ComputeMessageSize(JspbEncodingOptions);
      }
      if (PrintUnknownFields != false) {
        size += 1 + 1;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ConformanceRequest other) {
      if (other == null) {
        return;
      }
      if (other.RequestedOutputFormat != global::Conformance.WireFormat.Unspecified) {
        RequestedOutputFormat = other.RequestedOutputFormat;
      }
      if (other.MessageType.Length != 0) {
        MessageType = other.MessageType;
      }
      if (other.TestCategory != global::Conformance.TestCategory.UnspecifiedTest) {
        TestCategory = other.TestCategory;
      }
      if (other.jspbEncodingOptions_ != null) {
        if (jspbEncodingOptions_ == null) {
          JspbEncodingOptions = new global::Conformance.JspbEncodingConfig();
        }
        JspbEncodingOptions.MergeFrom(other.JspbEncodingOptions);
      }
      if (other.PrintUnknownFields != false) {
        PrintUnknownFields = other.PrintUnknownFields;
      }
      switch (other.PayloadCase) {
        case PayloadOneofCase.ProtobufPayload:
          ProtobufPayload = other.ProtobufPayload;
          break;
        case PayloadOneofCase.JsonPayload:
          JsonPayload = other.JsonPayload;
          break;
        case PayloadOneofCase.JspbPayload:
          JspbPayload = other.JspbPayload;
          break;
        case PayloadOneofCase.TextPayload:
          TextPayload = other.TextPayload;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            ProtobufPayload = input.ReadBytes();
            break;
          }
          case 18: {
            JsonPayload = input.ReadString();
            break;
          }
          case 24: {
            RequestedOutputFormat = (global::Conformance.WireFormat) input.ReadEnum();
            break;
          }
          case 34: {
            MessageType = input.ReadString();
            break;
          }
          case 40: {
            TestCategory = (global::Conformance.TestCategory) input.ReadEnum();
            break;
          }
          case 50: {
            if (jspbEncodingOptions_ == null) {
              JspbEncodingOptions = new global::Conformance.JspbEncodingConfig();
            }
            input.ReadMessage(JspbEncodingOptions);
            break;
          }
          case 58: {
            JspbPayload = input.ReadString();
            break;
          }
          case 66: {
            TextPayload = input.ReadString();
            break;
          }
          case 72: {
            PrintUnknownFields = input.ReadBool();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Represents a single test case's output.
  /// </summary>
  public sealed partial class ConformanceResponse : pb::IMessage<ConformanceResponse> {
    private static readonly pb::MessageParser<ConformanceResponse> _parser = new pb::MessageParser<ConformanceResponse>(() => new ConformanceResponse());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<ConformanceResponse> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[2]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ConformanceResponse() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ConformanceResponse(ConformanceResponse other) : this() {
      switch (other.ResultCase) {
        case ResultOneofCase.ParseError:
          ParseError = other.ParseError;
          break;
        case ResultOneofCase.SerializeError:
          SerializeError = other.SerializeError;
          break;
        case ResultOneofCase.RuntimeError:
          RuntimeError = other.RuntimeError;
          break;
        case ResultOneofCase.ProtobufPayload:
          ProtobufPayload = other.ProtobufPayload;
          break;
        case ResultOneofCase.JsonPayload:
          JsonPayload = other.JsonPayload;
          break;
        case ResultOneofCase.Skipped:
          Skipped = other.Skipped;
          break;
        case ResultOneofCase.JspbPayload:
          JspbPayload = other.JspbPayload;
          break;
        case ResultOneofCase.TextPayload:
          TextPayload = other.TextPayload;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ConformanceResponse Clone() {
      return new ConformanceResponse(this);
    }

    /// <summary>Field number for the "parse_error" field.</summary>
    public const int ParseErrorFieldNumber = 1;
    /// <summary>
    /// This string should be set to indicate parsing failed.  The string can
    /// provide more information about the parse error if it is available.
    ///
    /// Setting this string does not necessarily mean the testee failed the
    /// test.  Some of the test cases are intentionally invalid input.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string ParseError {
      get { return resultCase_ == ResultOneofCase.ParseError ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.ParseError;
      }
    }

    /// <summary>Field number for the "serialize_error" field.</summary>
    public const int SerializeErrorFieldNumber = 6;
    /// <summary>
    /// If the input was successfully parsed but errors occurred when
    /// serializing it to the requested output format, set the error message in
    /// this field.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string SerializeError {
      get { return resultCase_ == ResultOneofCase.SerializeError ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.SerializeError;
      }
    }

    /// <summary>Field number for the "runtime_error" field.</summary>
    public const int RuntimeErrorFieldNumber = 2;
    /// <summary>
    /// This should be set if some other error occurred.  This will always
    /// indicate that the test failed.  The string can provide more information
    /// about the failure.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string RuntimeError {
      get { return resultCase_ == ResultOneofCase.RuntimeError ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.RuntimeError;
      }
    }

    /// <summary>Field number for the "protobuf_payload" field.</summary>
    public const int ProtobufPayloadFieldNumber = 3;
    /// <summary>
    /// If the input was successfully parsed and the requested output was
    /// protobuf, serialize it to protobuf and set it in this field.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public pb::ByteString ProtobufPayload {
      get { return resultCase_ == ResultOneofCase.ProtobufPayload ? (pb::ByteString) result_ : pb::ByteString.Empty; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.ProtobufPayload;
      }
    }

    /// <summary>Field number for the "json_payload" field.</summary>
    public const int JsonPayloadFieldNumber = 4;
    /// <summary>
    /// If the input was successfully parsed and the requested output was JSON,
    /// serialize to JSON and set it in this field.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string JsonPayload {
      get { return resultCase_ == ResultOneofCase.JsonPayload ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.JsonPayload;
      }
    }

    /// <summary>Field number for the "skipped" field.</summary>
    public const int SkippedFieldNumber = 5;
    /// <summary>
    /// For when the testee skipped the test, likely because a certain feature
    /// wasn't supported, like JSON input/output.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string Skipped {
      get { return resultCase_ == ResultOneofCase.Skipped ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.Skipped;
      }
    }

    /// <summary>Field number for the "jspb_payload" field.</summary>
    public const int JspbPayloadFieldNumber = 7;
    /// <summary>
    /// If the input was successfully parsed and the requested output was JSPB,
    /// serialize to JSPB and set it in this field. JSPB is google internal only
    /// format. Opensource testees can just skip it.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string JspbPayload {
      get { return resultCase_ == ResultOneofCase.JspbPayload ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.JspbPayload;
      }
    }

    /// <summary>Field number for the "text_payload" field.</summary>
    public const int TextPayloadFieldNumber = 8;
    /// <summary>
    /// If the input was successfully parsed and the requested output was
    /// TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public string TextPayload {
      get { return resultCase_ == ResultOneofCase.TextPayload ? (string) result_ : ""; }
      set {
        result_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
        resultCase_ = ResultOneofCase.TextPayload;
      }
    }

    private object result_;
    /// <summary>Enum of possible cases for the "result" oneof.</summary>
    public enum ResultOneofCase {
      None = 0,
      ParseError = 1,
      SerializeError = 6,
      RuntimeError = 2,
      ProtobufPayload = 3,
      JsonPayload = 4,
      Skipped = 5,
      JspbPayload = 7,
      TextPayload = 8,
    }
    private ResultOneofCase resultCase_ = ResultOneofCase.None;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public ResultOneofCase ResultCase {
      get { return resultCase_; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void ClearResult() {
      resultCase_ = ResultOneofCase.None;
      result_ = null;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as ConformanceResponse);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(ConformanceResponse other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (ParseError != other.ParseError) return false;
      if (SerializeError != other.SerializeError) return false;
      if (RuntimeError != other.RuntimeError) return false;
      if (ProtobufPayload != other.ProtobufPayload) return false;
      if (JsonPayload != other.JsonPayload) return false;
      if (Skipped != other.Skipped) return false;
      if (JspbPayload != other.JspbPayload) return false;
      if (TextPayload != other.TextPayload) return false;
      if (ResultCase != other.ResultCase) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (resultCase_ == ResultOneofCase.ParseError) hash ^= ParseError.GetHashCode();
      if (resultCase_ == ResultOneofCase.SerializeError) hash ^= SerializeError.GetHashCode();
      if (resultCase_ == ResultOneofCase.RuntimeError) hash ^= RuntimeError.GetHashCode();
      if (resultCase_ == ResultOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
      if (resultCase_ == ResultOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
      if (resultCase_ == ResultOneofCase.Skipped) hash ^= Skipped.GetHashCode();
      if (resultCase_ == ResultOneofCase.JspbPayload) hash ^= JspbPayload.GetHashCode();
      if (resultCase_ == ResultOneofCase.TextPayload) hash ^= TextPayload.GetHashCode();
      hash ^= (int) resultCase_;
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (resultCase_ == ResultOneofCase.ParseError) {
        output.WriteRawTag(10);
        output.WriteString(ParseError);
      }
      if (resultCase_ == ResultOneofCase.RuntimeError) {
        output.WriteRawTag(18);
        output.WriteString(RuntimeError);
      }
      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
        output.WriteRawTag(26);
        output.WriteBytes(ProtobufPayload);
      }
      if (resultCase_ == ResultOneofCase.JsonPayload) {
        output.WriteRawTag(34);
        output.WriteString(JsonPayload);
      }
      if (resultCase_ == ResultOneofCase.Skipped) {
        output.WriteRawTag(42);
        output.WriteString(Skipped);
      }
      if (resultCase_ == ResultOneofCase.SerializeError) {
        output.WriteRawTag(50);
        output.WriteString(SerializeError);
      }
      if (resultCase_ == ResultOneofCase.JspbPayload) {
        output.WriteRawTag(58);
        output.WriteString(JspbPayload);
      }
      if (resultCase_ == ResultOneofCase.TextPayload) {
        output.WriteRawTag(66);
        output.WriteString(TextPayload);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (resultCase_ == ResultOneofCase.ParseError) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(ParseError);
      }
      if (resultCase_ == ResultOneofCase.SerializeError) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(SerializeError);
      }
      if (resultCase_ == ResultOneofCase.RuntimeError) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(RuntimeError);
      }
      if (resultCase_ == ResultOneofCase.ProtobufPayload) {
        size += 1 + pb::CodedOutputStream.ComputeBytesSize(ProtobufPayload);
      }
      if (resultCase_ == ResultOneofCase.JsonPayload) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonPayload);
      }
      if (resultCase_ == ResultOneofCase.Skipped) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Skipped);
      }
      if (resultCase_ == ResultOneofCase.JspbPayload) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(JspbPayload);
      }
      if (resultCase_ == ResultOneofCase.TextPayload) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(TextPayload);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(ConformanceResponse other) {
      if (other == null) {
        return;
      }
      switch (other.ResultCase) {
        case ResultOneofCase.ParseError:
          ParseError = other.ParseError;
          break;
        case ResultOneofCase.SerializeError:
          SerializeError = other.SerializeError;
          break;
        case ResultOneofCase.RuntimeError:
          RuntimeError = other.RuntimeError;
          break;
        case ResultOneofCase.ProtobufPayload:
          ProtobufPayload = other.ProtobufPayload;
          break;
        case ResultOneofCase.JsonPayload:
          JsonPayload = other.JsonPayload;
          break;
        case ResultOneofCase.Skipped:
          Skipped = other.Skipped;
          break;
        case ResultOneofCase.JspbPayload:
          JspbPayload = other.JspbPayload;
          break;
        case ResultOneofCase.TextPayload:
          TextPayload = other.TextPayload;
          break;
      }

      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            ParseError = input.ReadString();
            break;
          }
          case 18: {
            RuntimeError = input.ReadString();
            break;
          }
          case 26: {
            ProtobufPayload = input.ReadBytes();
            break;
          }
          case 34: {
            JsonPayload = input.ReadString();
            break;
          }
          case 42: {
            Skipped = input.ReadString();
            break;
          }
          case 50: {
            SerializeError = input.ReadString();
            break;
          }
          case 58: {
            JspbPayload = input.ReadString();
            break;
          }
          case 66: {
            TextPayload = input.ReadString();
            break;
          }
        }
      }
    }

  }

  /// <summary>
  /// Encoding options for jspb format.
  /// </summary>
  public sealed partial class JspbEncodingConfig : pb::IMessage<JspbEncodingConfig> {
    private static readonly pb::MessageParser<JspbEncodingConfig> _parser = new pb::MessageParser<JspbEncodingConfig>(() => new JspbEncodingConfig());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pb::MessageParser<JspbEncodingConfig> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[3]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public JspbEncodingConfig() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public JspbEncodingConfig(JspbEncodingConfig other) : this() {
      useJspbArrayAnyFormat_ = other.useJspbArrayAnyFormat_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public JspbEncodingConfig Clone() {
      return new JspbEncodingConfig(this);
    }

    /// <summary>Field number for the "use_jspb_array_any_format" field.</summary>
    public const int UseJspbArrayAnyFormatFieldNumber = 1;
    private bool useJspbArrayAnyFormat_;
    /// <summary>
    /// Encode the value field of Any as jspb array if ture, otherwise binary.
    /// </summary>
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool UseJspbArrayAnyFormat {
      get { return useJspbArrayAnyFormat_; }
      set {
        useJspbArrayAnyFormat_ = value;
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override bool Equals(object other) {
      return Equals(other as JspbEncodingConfig);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public bool Equals(JspbEncodingConfig other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (UseJspbArrayAnyFormat != other.UseJspbArrayAnyFormat) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override int GetHashCode() {
      int hash = 1;
      if (UseJspbArrayAnyFormat != false) hash ^= UseJspbArrayAnyFormat.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public override string ToString() {
      return pb::JsonFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void WriteTo(pb::CodedOutputStream output) {
      if (UseJspbArrayAnyFormat != false) {
        output.WriteRawTag(8);
        output.WriteBool(UseJspbArrayAnyFormat);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public int CalculateSize() {
      int size = 0;
      if (UseJspbArrayAnyFormat != false) {
        size += 1 + 1;
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(JspbEncodingConfig other) {
      if (other == null) {
        return;
      }
      if (other.UseJspbArrayAnyFormat != false) {
        UseJspbArrayAnyFormat = other.UseJspbArrayAnyFormat;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    public void MergeFrom(pb::CodedInputStream input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 8: {
            UseJspbArrayAnyFormat = input.ReadBool();
            break;
          }
        }
      }
    }

  }

  #endregion

}

#endregion Designer generated code
