// @generated by protobuf-ts 2.8.2 with parameter long_type_string
// @generated from protobuf file "pb/state/state.proto" (syntax proto3)
// tslint:disable
import type { BinaryWriteOptions } from '@protobuf-ts/runtime';
import type { IBinaryWriter } from '@protobuf-ts/runtime';
import { WireType } from '@protobuf-ts/runtime';
import type { BinaryReadOptions } from '@protobuf-ts/runtime';
import type { IBinaryReader } from '@protobuf-ts/runtime';
import { UnknownFieldHandler } from '@protobuf-ts/runtime';
import type { PartialMessage } from '@protobuf-ts/runtime';
import { reflectionMergePartial } from '@protobuf-ts/runtime';
import { MESSAGE_TYPE } from '@protobuf-ts/runtime';
import { MessageType } from '@protobuf-ts/runtime';
import { TestGroup } from '../config/config';
import { Timestamp } from '../../google/protobuf/timestamp';
/**
 * @generated from protobuf message Property
 */
export interface Property {
  /**
   * @generated from protobuf field: map<string, string> property = 1;
   */
  property: {
    [key: string]: string;
  };
}
/**
 * A metric and its values for each test cycle.
 *
 * @generated from protobuf message Metric
 */
export interface Metric {
  /**
   * @generated from protobuf field: string name = 1;
   */
  name: string; // Name of metric, such as duration
  /**
   * Sparse encoding of values. Indices is a list of pairs of <index, count>
   * that details columns with metric values. So given:
   *   Indices: [0, 2, 6, 4]
   *   Values: [0.1,0.2,6.1,6.2,6.3,6.4]
   * Decoded 12-value equivalent is:
   * [0.1, 0.2, nil, nil, nil, nil, 6.1, 6.2, 6.3, 6.4, nil, nil, ...]
   *
   * @generated from protobuf field: repeated int32 indices = 2;
   */
  indices: number[]; // n=index of first value, n+1=count of filled values
  /**
   * @generated from protobuf field: repeated double values = 3;
   */
  values: number[]; // only present for columns with a metric value
}
/**
 * @generated from protobuf message UpdatePhaseData
 */
export interface UpdatePhaseData {
  /**
   * The name for a part of the update cycle.
   *
   * @generated from protobuf field: string phase_name = 1;
   */
  phaseName: string;
  /**
   * Time taken for a part of the update cycle, in seconds.
   *
   * @generated from protobuf field: double phase_seconds = 2;
   */
  phaseSeconds: number;
}
/**
 * Info on time taken to update test results during the last update cycle.
 *
 * @generated from protobuf message UpdateInfo
 */
export interface UpdateInfo {
  /**
   * Metrics for how long parts of the update cycle take.
   *
   * @generated from protobuf field: repeated UpdatePhaseData update_phase_data = 1;
   */
  updatePhaseData: UpdatePhaseData[];
}
/**
 * Info on a failing test row about the failure.
 *
 * @generated from protobuf message AlertInfo
 */
export interface AlertInfo {
  /**
   * Number of results that have failed.
   *
   * @generated from protobuf field: int32 fail_count = 1;
   */
  failCount: number;
  /**
   * The build ID the test first failed at.
   *
   * @generated from protobuf field: string fail_build_id = 2;
   */
  failBuildId: string;
  /**
   * The time the test first failed at.
   *
   * @generated from protobuf field: google.protobuf.Timestamp fail_time = 3;
   */
  failTime?: Timestamp;
  /**
   * The test ID for the first test failure.
   *
   * @generated from protobuf field: string fail_test_id = 4;
   */
  failTestId: string;
  /**
   * The build ID the test last passed at.
   *
   * @generated from protobuf field: string pass_build_id = 5;
   */
  passBuildId: string;
  /**
   * The time the test last passed at.
   *
   * @generated from protobuf field: google.protobuf.Timestamp pass_time = 6;
   */
  passTime?: Timestamp;
  /**
   * A snippet explaining the failure.
   *
   * @generated from protobuf field: string failure_message = 7;
   */
  failureMessage: string;
  /**
   * Link to search for build changes, internally a code-search link.
   *
   * @generated from protobuf field: string build_link = 8;
   */
  buildLink: string;
  /**
   * Text for option to search for build changes.
   *
   * @generated from protobuf field: string build_link_text = 9;
   */
  buildLinkText: string;
  /**
   * Text to display for link to search for build changes.
   *
   * @generated from protobuf field: string build_url_text = 10;
   */
  buildUrlText: string;
  /**
   * The build ID for the latest test failure. (Does not indicate the failure is
   * 'over', just the latest test failure we found.)
   *
   * @generated from protobuf field: string latest_fail_build_id = 11;
   */
  latestFailBuildId: string;
  /**
   * The test ID for the latest test failure.
   *
   * @generated from protobuf field: string latest_fail_test_id = 14;
   */
  latestFailTestId: string;
  /**
   * Maps (property name):(property value) for arbitrary alert properties.
   *
   * @generated from protobuf field: map<string, string> properties = 12;
   */
  properties: {
    [key: string]: string;
  };
  /**
   * A list of IDs for issue hotlists related to this failure.
   *
   * @generated from protobuf field: repeated string hotlist_ids = 13;
   */
  hotlistIds: string[];
  /**
   * Dynamic email list, route email alerts to these instead of the configured
   * defaults.
   *
   * @generated from protobuf field: repeated string email_addresses = 15;
   */
  emailAddresses: string[];
}
/**
 * Info on default test metadata for a dashboard tab.
 *
 * @generated from protobuf message TestMetadata
 */
export interface TestMetadata {
  /**
   * Name of the test with associated test metadata.
   *
   * @generated from protobuf field: string test_name = 1;
   */
  testName: string;
  /**
   * Default bug component.
   *
   * @generated from protobuf field: int32 bug_component = 2;
   */
  bugComponent: number;
  /**
   * Default owner.
   *
   * @generated from protobuf field: string owner = 3;
   */
  owner: string;
  /**
   * Default list of cc's.
   *
   * @generated from protobuf field: repeated string cc = 4;
   */
  cc: string[];
  /**
   * When present, only file a bug for failed tests with same error type.
   * Otherwise, always file a bug.
   *
   * @generated from protobuf field: string error_type = 5;
   */
  errorType: string;
}
/**
 * TestGrid column headers. Does not contain the individual cells.
 *
 * @generated from protobuf message Column
 */
export interface Column {
  /**
   * Unique instance of the job, typically BUILD_NUMBER from prow or a guid
   *
   * @generated from protobuf field: string build = 1;
   */
  build: string;
  /**
   * Name associated with the column (such as the run/invocation ID).No two
   * columns should have the same build_id and name. The name field allows the
   * display of multiple columns with the same build_id.
   *
   * @generated from protobuf field: string name = 2;
   */
  name: string;
  /**
   * Milliseconds since start of epoch (python time.time() * 1000)
   * TODO(#683): Use a timestamp, not this double
   *
   * @generated from protobuf field: double started = 3;
   */
  started: number;
  /**
   * Additional custom headers like commit, image used, etc.
   *
   * @generated from protobuf field: repeated string extra = 4;
   */
  extra: string[];
  /**
   * Custom hotlist ids.
   *
   * @generated from protobuf field: string hotlist_ids = 5;
   */
  hotlistIds: string;
  /**
   * An optional hint for the updater.
   *
   * @generated from protobuf field: string hint = 6;
   */
  hint: string;
  /**
   * Dynamic email list, route email alerts to these instead of the configured
   * defaults.
   *
   * @generated from protobuf field: repeated string email_addresses = 7;
   */
  emailAddresses: string[];
  /**
   * Status totals for the column.
   * Only written in tab state, if a broken threshold is defined for columns.
   *
   * @generated from protobuf field: Stats stats = 8;
   */
  stats?: Stats;
}
/**
 * @generated from protobuf message Stats
 */
export interface Stats {
  /**
   * @generated from protobuf field: int32 fail_count = 1;
   */
  failCount: number;
  /**
   * @generated from protobuf field: int32 pass_count = 2;
   */
  passCount: number;
  /**
   * @generated from protobuf field: int32 total_count = 3;
   */
  totalCount: number;
  /**
   * True if this column has any in-progress runs.
   *
   * @generated from protobuf field: bool pending = 4;
   */
  pending: boolean;
  /**
   * True if a broken threshold is defined, and this column's fail/total ratio
   * exceeds it.
   *
   * @generated from protobuf field: bool broken = 5;
   */
  broken: boolean;
}
/**
 * TestGrid rows
 *
 * @generated from protobuf message Row
 */
export interface Row {
  /**
   * Display name, which might process id to append/filter info.
   *
   * @generated from protobuf field: string name = 1;
   */
  name: string;
  /**
   * raw id for the row, such as the bazel target or golang package.
   *
   * @generated from protobuf field: string id = 2;
   */
  id: string;
  /**
   * Results for this row, run-length encoded to reduce size/improve
   * performance. Thus (encoded -> decoded equivalent):
   *   [0, 3, 5, 4] -> [0, 0, 0, 5, 5, 5, 5]
   *   [5, 1] -> [5]
   *   [1, 5] -> [1, 1, 1, 1, 1]
   * The decoded values are Result enums
   *
   * @generated from protobuf field: repeated int32 results = 3;
   */
  results: number[];
  /**
   * Test IDs for each test result in this test case.
   * Must be present on every column, regardless of status.
   *
   * @generated from protobuf field: repeated string cell_ids = 4;
   */
  cellIds: string[];
  /**
   * Short description of the result, displayed on mouseover.
   * Present for any column with a non-empty status (not NO_RESULT).
   *
   * @generated from protobuf field: repeated string messages = 5;
   */
  messages: string[];
  /**
   * Names of metrics associated with this test case. Stored separate from
   * metric info (which may be omitted).
   *
   * @generated from protobuf field: repeated string metric = 7;
   */
  metric: string[];
  /**
   * @generated from protobuf field: repeated Metric metrics = 8;
   */
  metrics: Metric[]; // Numerical performance/timing data, etc.
  /**
   * Short string to place inside the cell (F for fail, etc)
   * Present for any column with a non-empty status (not NO_RESULT).
   *
   * @generated from protobuf field: repeated string icons = 9;
   */
  icons: string[];
  /**
   * IDs for issues associated with this row.
   *
   * @generated from protobuf field: repeated string issues = 10;
   */
  issues: string[];
  /**
   * An alert for the failure if there's a recent failure for this row.
   *
   * @generated from protobuf field: AlertInfo alert_info = 11;
   */
  alertInfo?: AlertInfo;
  /**
   * Values of a user-defined property found in cells for this row.
   * TODO: Fold this into `properties` field.
   *
   * @generated from protobuf field: repeated string user_property = 12;
   */
  userProperty: string[];
  /**
   * General key-value pairs associated with cells in this row.
   * Present for any column with a non-empty status (not NO_RESULT).
   *
   * @generated from protobuf field: repeated Property properties = 13;
   */
  properties: Property[];
}
/**
 * A single table of test results backing a dashboard tab.
 *
 * @generated from protobuf message Grid
 */
export interface Grid {
  /**
   * A cycle of test results, not including the results. In the TestGrid client,
   * the cycles define the columns.
   *
   * @generated from protobuf field: repeated Column columns = 1;
   */
  columns: Column[];
  /**
   * A test case with test results. In the TestGrid client, the cases define the
   * rows (and the results define the individual cells).
   *
   * @generated from protobuf field: repeated Row rows = 2;
   */
  rows: Row[];
  /**
   * The latest configuration used to generate this test group.
   *
   * @generated from protobuf field: TestGroup config = 4;
   */
  config?: TestGroup;
  /**
   * Seconds since epoch for last time this cycle was updated.
   *
   * @generated from protobuf field: double last_time_updated = 6;
   */
  lastTimeUpdated: number;
  /**
   * Stored info on previous timing for parts of the update cycle.
   *
   * @generated from protobuf field: repeated UpdateInfo update_info = 8;
   */
  updateInfo: UpdateInfo[];
  /**
   * Stored info on default test metadata.
   *
   * @generated from protobuf field: repeated TestMetadata test_metadata = 9;
   */
  testMetadata: TestMetadata[];
  /**
   * Clusters of failures for a TestResultTable instance.
   *
   * @generated from protobuf field: repeated Cluster cluster = 10;
   */
  cluster: Cluster[];
  /**
   * Most recent timestamp that clusters have processed.
   *
   * @generated from protobuf field: double most_recent_cluster_timestamp = 11;
   */
  mostRecentClusterTimestamp: number;
}
/**
 * A cluster of failures grouped by test status and message for a test results
 * table.
 *
 * @generated from protobuf message Cluster
 */
export interface Cluster {
  /**
   * Test status cluster grouped by.
   *
   * @generated from protobuf field: int32 test_status = 1;
   */
  testStatus: number;
  /**
   * Error message or testFailureClassification string cluster grouped by.
   *
   * @generated from protobuf field: string message = 2;
   */
  message: string;
  /**
   * ClusterRows that belong to this cluster.
   *
   * @generated from protobuf field: repeated ClusterRow cluster_row = 3;
   */
  clusterRow: ClusterRow[];
}
/**
 * Cells in a TestRow that belong to a specific Cluster.
 *
 * @generated from protobuf message ClusterRow
 */
export interface ClusterRow {
  /**
   * Name of TestRow.
   *
   * @generated from protobuf field: string display_name = 1;
   */
  displayName: string;
  /**
   * Index within row that belongs to Cluster (refer to columns of the row).
   *
   * @generated from protobuf field: repeated int32 index = 2;
   */
  index: number[];
}
// @generated message type with reflection information, may provide speed optimized methods
class Property$Type extends MessageType<Property> {
  constructor() {
    super('Property', [
      {
        no: 1,
        name: 'property',
        kind: 'map',
        K: 9 /*ScalarType.STRING*/,
        V: { kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      },
    ]);
  }
  create(value?: PartialMessage<Property>): Property {
    const message = { property: {} };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<Property>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Property
  ): Property {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* map<string, string> property */ 1:
          this.binaryReadMap1(message.property, reader, options);
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  private binaryReadMap1(
    map: Property['property'],
    reader: IBinaryReader,
    options: BinaryReadOptions
  ): void {
    let len = reader.uint32(),
      end = reader.pos + len,
      key: keyof Property['property'] | undefined,
      val: Property['property'][any] | undefined;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case 1:
          key = reader.string();
          break;
        case 2:
          val = reader.string();
          break;
        default:
          throw new globalThis.Error(
            'unknown map entry field for field Property.property'
          );
      }
    }
    map[key ?? ''] = val ?? '';
  }
  internalBinaryWrite(
    message: Property,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* map<string, string> property = 1; */
    for (let k of Object.keys(message.property))
      writer
        .tag(1, WireType.LengthDelimited)
        .fork()
        .tag(1, WireType.LengthDelimited)
        .string(k)
        .tag(2, WireType.LengthDelimited)
        .string(message.property[k])
        .join();
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Property
 */
export const Property = new Property$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Metric$Type extends MessageType<Metric> {
  constructor() {
    super('Metric', [
      { no: 1, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 2,
        name: 'indices',
        kind: 'scalar',
        repeat: 1 /*RepeatType.PACKED*/,
        T: 5 /*ScalarType.INT32*/,
      },
      {
        no: 3,
        name: 'values',
        kind: 'scalar',
        repeat: 1 /*RepeatType.PACKED*/,
        T: 1 /*ScalarType.DOUBLE*/,
      },
    ]);
  }
  create(value?: PartialMessage<Metric>): Metric {
    const message = { name: '', indices: [], values: [] };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<Metric>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Metric
  ): Metric {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* string name */ 1:
          message.name = reader.string();
          break;
        case /* repeated int32 indices */ 2:
          if (wireType === WireType.LengthDelimited)
            for (let e = reader.int32() + reader.pos; reader.pos < e; )
              message.indices.push(reader.int32());
          else message.indices.push(reader.int32());
          break;
        case /* repeated double values */ 3:
          if (wireType === WireType.LengthDelimited)
            for (let e = reader.int32() + reader.pos; reader.pos < e; )
              message.values.push(reader.double());
          else message.values.push(reader.double());
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: Metric,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* string name = 1; */
    if (message.name !== '')
      writer.tag(1, WireType.LengthDelimited).string(message.name);
    /* repeated int32 indices = 2; */
    if (message.indices.length) {
      writer.tag(2, WireType.LengthDelimited).fork();
      for (let i = 0; i < message.indices.length; i++)
        writer.int32(message.indices[i]);
      writer.join();
    }
    /* repeated double values = 3; */
    if (message.values.length) {
      writer.tag(3, WireType.LengthDelimited).fork();
      for (let i = 0; i < message.values.length; i++)
        writer.double(message.values[i]);
      writer.join();
    }
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Metric
 */
export const Metric = new Metric$Type();
// @generated message type with reflection information, may provide speed optimized methods
class UpdatePhaseData$Type extends MessageType<UpdatePhaseData> {
  constructor() {
    super('UpdatePhaseData', [
      { no: 1, name: 'phase_name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 2,
        name: 'phase_seconds',
        kind: 'scalar',
        T: 1 /*ScalarType.DOUBLE*/,
      },
    ]);
  }
  create(value?: PartialMessage<UpdatePhaseData>): UpdatePhaseData {
    const message = { phaseName: '', phaseSeconds: 0 };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<UpdatePhaseData>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: UpdatePhaseData
  ): UpdatePhaseData {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* string phase_name */ 1:
          message.phaseName = reader.string();
          break;
        case /* double phase_seconds */ 2:
          message.phaseSeconds = reader.double();
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: UpdatePhaseData,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* string phase_name = 1; */
    if (message.phaseName !== '')
      writer.tag(1, WireType.LengthDelimited).string(message.phaseName);
    /* double phase_seconds = 2; */
    if (message.phaseSeconds !== 0)
      writer.tag(2, WireType.Bit64).double(message.phaseSeconds);
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message UpdatePhaseData
 */
export const UpdatePhaseData = new UpdatePhaseData$Type();
// @generated message type with reflection information, may provide speed optimized methods
class UpdateInfo$Type extends MessageType<UpdateInfo> {
  constructor() {
    super('UpdateInfo', [
      {
        no: 1,
        name: 'update_phase_data',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => UpdatePhaseData,
      },
    ]);
  }
  create(value?: PartialMessage<UpdateInfo>): UpdateInfo {
    const message = { updatePhaseData: [] };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<UpdateInfo>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: UpdateInfo
  ): UpdateInfo {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* repeated UpdatePhaseData update_phase_data */ 1:
          message.updatePhaseData.push(
            UpdatePhaseData.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: UpdateInfo,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* repeated UpdatePhaseData update_phase_data = 1; */
    for (let i = 0; i < message.updatePhaseData.length; i++)
      UpdatePhaseData.internalBinaryWrite(
        message.updatePhaseData[i],
        writer.tag(1, WireType.LengthDelimited).fork(),
        options
      ).join();
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message UpdateInfo
 */
export const UpdateInfo = new UpdateInfo$Type();
// @generated message type with reflection information, may provide speed optimized methods
class AlertInfo$Type extends MessageType<AlertInfo> {
  constructor() {
    super('AlertInfo', [
      { no: 1, name: 'fail_count', kind: 'scalar', T: 5 /*ScalarType.INT32*/ },
      {
        no: 2,
        name: 'fail_build_id',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 3, name: 'fail_time', kind: 'message', T: () => Timestamp },
      {
        no: 4,
        name: 'fail_test_id',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 5,
        name: 'pass_build_id',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 6, name: 'pass_time', kind: 'message', T: () => Timestamp },
      {
        no: 7,
        name: 'failure_message',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 8, name: 'build_link', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 9,
        name: 'build_link_text',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 10,
        name: 'build_url_text',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 11,
        name: 'latest_fail_build_id',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 14,
        name: 'latest_fail_test_id',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 12,
        name: 'properties',
        kind: 'map',
        K: 9 /*ScalarType.STRING*/,
        V: { kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      },
      {
        no: 13,
        name: 'hotlist_ids',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 15,
        name: 'email_addresses',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
    ]);
  }
  create(value?: PartialMessage<AlertInfo>): AlertInfo {
    const message = {
      failCount: 0,
      failBuildId: '',
      failTestId: '',
      passBuildId: '',
      failureMessage: '',
      buildLink: '',
      buildLinkText: '',
      buildUrlText: '',
      latestFailBuildId: '',
      latestFailTestId: '',
      properties: {},
      hotlistIds: [],
      emailAddresses: [],
    };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<AlertInfo>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: AlertInfo
  ): AlertInfo {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* int32 fail_count */ 1:
          message.failCount = reader.int32();
          break;
        case /* string fail_build_id */ 2:
          message.failBuildId = reader.string();
          break;
        case /* google.protobuf.Timestamp fail_time */ 3:
          message.failTime = Timestamp.internalBinaryRead(
            reader,
            reader.uint32(),
            options,
            message.failTime
          );
          break;
        case /* string fail_test_id */ 4:
          message.failTestId = reader.string();
          break;
        case /* string pass_build_id */ 5:
          message.passBuildId = reader.string();
          break;
        case /* google.protobuf.Timestamp pass_time */ 6:
          message.passTime = Timestamp.internalBinaryRead(
            reader,
            reader.uint32(),
            options,
            message.passTime
          );
          break;
        case /* string failure_message */ 7:
          message.failureMessage = reader.string();
          break;
        case /* string build_link */ 8:
          message.buildLink = reader.string();
          break;
        case /* string build_link_text */ 9:
          message.buildLinkText = reader.string();
          break;
        case /* string build_url_text */ 10:
          message.buildUrlText = reader.string();
          break;
        case /* string latest_fail_build_id */ 11:
          message.latestFailBuildId = reader.string();
          break;
        case /* string latest_fail_test_id */ 14:
          message.latestFailTestId = reader.string();
          break;
        case /* map<string, string> properties */ 12:
          this.binaryReadMap12(message.properties, reader, options);
          break;
        case /* repeated string hotlist_ids */ 13:
          message.hotlistIds.push(reader.string());
          break;
        case /* repeated string email_addresses */ 15:
          message.emailAddresses.push(reader.string());
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  private binaryReadMap12(
    map: AlertInfo['properties'],
    reader: IBinaryReader,
    options: BinaryReadOptions
  ): void {
    let len = reader.uint32(),
      end = reader.pos + len,
      key: keyof AlertInfo['properties'] | undefined,
      val: AlertInfo['properties'][any] | undefined;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case 1:
          key = reader.string();
          break;
        case 2:
          val = reader.string();
          break;
        default:
          throw new globalThis.Error(
            'unknown map entry field for field AlertInfo.properties'
          );
      }
    }
    map[key ?? ''] = val ?? '';
  }
  internalBinaryWrite(
    message: AlertInfo,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* int32 fail_count = 1; */
    if (message.failCount !== 0)
      writer.tag(1, WireType.Varint).int32(message.failCount);
    /* string fail_build_id = 2; */
    if (message.failBuildId !== '')
      writer.tag(2, WireType.LengthDelimited).string(message.failBuildId);
    /* google.protobuf.Timestamp fail_time = 3; */
    if (message.failTime)
      Timestamp.internalBinaryWrite(
        message.failTime,
        writer.tag(3, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* string fail_test_id = 4; */
    if (message.failTestId !== '')
      writer.tag(4, WireType.LengthDelimited).string(message.failTestId);
    /* string pass_build_id = 5; */
    if (message.passBuildId !== '')
      writer.tag(5, WireType.LengthDelimited).string(message.passBuildId);
    /* google.protobuf.Timestamp pass_time = 6; */
    if (message.passTime)
      Timestamp.internalBinaryWrite(
        message.passTime,
        writer.tag(6, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* string failure_message = 7; */
    if (message.failureMessage !== '')
      writer.tag(7, WireType.LengthDelimited).string(message.failureMessage);
    /* string build_link = 8; */
    if (message.buildLink !== '')
      writer.tag(8, WireType.LengthDelimited).string(message.buildLink);
    /* string build_link_text = 9; */
    if (message.buildLinkText !== '')
      writer.tag(9, WireType.LengthDelimited).string(message.buildLinkText);
    /* string build_url_text = 10; */
    if (message.buildUrlText !== '')
      writer.tag(10, WireType.LengthDelimited).string(message.buildUrlText);
    /* string latest_fail_build_id = 11; */
    if (message.latestFailBuildId !== '')
      writer
        .tag(11, WireType.LengthDelimited)
        .string(message.latestFailBuildId);
    /* string latest_fail_test_id = 14; */
    if (message.latestFailTestId !== '')
      writer.tag(14, WireType.LengthDelimited).string(message.latestFailTestId);
    /* map<string, string> properties = 12; */
    for (let k of Object.keys(message.properties))
      writer
        .tag(12, WireType.LengthDelimited)
        .fork()
        .tag(1, WireType.LengthDelimited)
        .string(k)
        .tag(2, WireType.LengthDelimited)
        .string(message.properties[k])
        .join();
    /* repeated string hotlist_ids = 13; */
    for (let i = 0; i < message.hotlistIds.length; i++)
      writer.tag(13, WireType.LengthDelimited).string(message.hotlistIds[i]);
    /* repeated string email_addresses = 15; */
    for (let i = 0; i < message.emailAddresses.length; i++)
      writer
        .tag(15, WireType.LengthDelimited)
        .string(message.emailAddresses[i]);
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message AlertInfo
 */
export const AlertInfo = new AlertInfo$Type();
// @generated message type with reflection information, may provide speed optimized methods
class TestMetadata$Type extends MessageType<TestMetadata> {
  constructor() {
    super('TestMetadata', [
      { no: 1, name: 'test_name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 2,
        name: 'bug_component',
        kind: 'scalar',
        T: 5 /*ScalarType.INT32*/,
      },
      { no: 3, name: 'owner', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 4,
        name: 'cc',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 5, name: 'error_type', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
    ]);
  }
  create(value?: PartialMessage<TestMetadata>): TestMetadata {
    const message = {
      testName: '',
      bugComponent: 0,
      owner: '',
      cc: [],
      errorType: '',
    };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<TestMetadata>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: TestMetadata
  ): TestMetadata {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* string test_name */ 1:
          message.testName = reader.string();
          break;
        case /* int32 bug_component */ 2:
          message.bugComponent = reader.int32();
          break;
        case /* string owner */ 3:
          message.owner = reader.string();
          break;
        case /* repeated string cc */ 4:
          message.cc.push(reader.string());
          break;
        case /* string error_type */ 5:
          message.errorType = reader.string();
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: TestMetadata,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* string test_name = 1; */
    if (message.testName !== '')
      writer.tag(1, WireType.LengthDelimited).string(message.testName);
    /* int32 bug_component = 2; */
    if (message.bugComponent !== 0)
      writer.tag(2, WireType.Varint).int32(message.bugComponent);
    /* string owner = 3; */
    if (message.owner !== '')
      writer.tag(3, WireType.LengthDelimited).string(message.owner);
    /* repeated string cc = 4; */
    for (let i = 0; i < message.cc.length; i++)
      writer.tag(4, WireType.LengthDelimited).string(message.cc[i]);
    /* string error_type = 5; */
    if (message.errorType !== '')
      writer.tag(5, WireType.LengthDelimited).string(message.errorType);
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message TestMetadata
 */
export const TestMetadata = new TestMetadata$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Column$Type extends MessageType<Column> {
  constructor() {
    super('Column', [
      { no: 1, name: 'build', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      { no: 2, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      { no: 3, name: 'started', kind: 'scalar', T: 1 /*ScalarType.DOUBLE*/ },
      {
        no: 4,
        name: 'extra',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 5,
        name: 'hotlist_ids',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 6, name: 'hint', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 7,
        name: 'email_addresses',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 8, name: 'stats', kind: 'message', T: () => Stats },
    ]);
  }
  create(value?: PartialMessage<Column>): Column {
    const message = {
      build: '',
      name: '',
      started: 0,
      extra: [],
      hotlistIds: '',
      hint: '',
      emailAddresses: [],
    };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<Column>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Column
  ): Column {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* string build */ 1:
          message.build = reader.string();
          break;
        case /* string name */ 2:
          message.name = reader.string();
          break;
        case /* double started */ 3:
          message.started = reader.double();
          break;
        case /* repeated string extra */ 4:
          message.extra.push(reader.string());
          break;
        case /* string hotlist_ids */ 5:
          message.hotlistIds = reader.string();
          break;
        case /* string hint */ 6:
          message.hint = reader.string();
          break;
        case /* repeated string email_addresses */ 7:
          message.emailAddresses.push(reader.string());
          break;
        case /* Stats stats */ 8:
          message.stats = Stats.internalBinaryRead(
            reader,
            reader.uint32(),
            options,
            message.stats
          );
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: Column,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* string build = 1; */
    if (message.build !== '')
      writer.tag(1, WireType.LengthDelimited).string(message.build);
    /* string name = 2; */
    if (message.name !== '')
      writer.tag(2, WireType.LengthDelimited).string(message.name);
    /* double started = 3; */
    if (message.started !== 0)
      writer.tag(3, WireType.Bit64).double(message.started);
    /* repeated string extra = 4; */
    for (let i = 0; i < message.extra.length; i++)
      writer.tag(4, WireType.LengthDelimited).string(message.extra[i]);
    /* string hotlist_ids = 5; */
    if (message.hotlistIds !== '')
      writer.tag(5, WireType.LengthDelimited).string(message.hotlistIds);
    /* string hint = 6; */
    if (message.hint !== '')
      writer.tag(6, WireType.LengthDelimited).string(message.hint);
    /* repeated string email_addresses = 7; */
    for (let i = 0; i < message.emailAddresses.length; i++)
      writer.tag(7, WireType.LengthDelimited).string(message.emailAddresses[i]);
    /* Stats stats = 8; */
    if (message.stats)
      Stats.internalBinaryWrite(
        message.stats,
        writer.tag(8, WireType.LengthDelimited).fork(),
        options
      ).join();
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Column
 */
export const Column = new Column$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Stats$Type extends MessageType<Stats> {
  constructor() {
    super('Stats', [
      { no: 1, name: 'fail_count', kind: 'scalar', T: 5 /*ScalarType.INT32*/ },
      { no: 2, name: 'pass_count', kind: 'scalar', T: 5 /*ScalarType.INT32*/ },
      { no: 3, name: 'total_count', kind: 'scalar', T: 5 /*ScalarType.INT32*/ },
      { no: 4, name: 'pending', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
      { no: 5, name: 'broken', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
    ]);
  }
  create(value?: PartialMessage<Stats>): Stats {
    const message = {
      failCount: 0,
      passCount: 0,
      totalCount: 0,
      pending: false,
      broken: false,
    };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<Stats>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Stats
  ): Stats {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* int32 fail_count */ 1:
          message.failCount = reader.int32();
          break;
        case /* int32 pass_count */ 2:
          message.passCount = reader.int32();
          break;
        case /* int32 total_count */ 3:
          message.totalCount = reader.int32();
          break;
        case /* bool pending */ 4:
          message.pending = reader.bool();
          break;
        case /* bool broken */ 5:
          message.broken = reader.bool();
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: Stats,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* int32 fail_count = 1; */
    if (message.failCount !== 0)
      writer.tag(1, WireType.Varint).int32(message.failCount);
    /* int32 pass_count = 2; */
    if (message.passCount !== 0)
      writer.tag(2, WireType.Varint).int32(message.passCount);
    /* int32 total_count = 3; */
    if (message.totalCount !== 0)
      writer.tag(3, WireType.Varint).int32(message.totalCount);
    /* bool pending = 4; */
    if (message.pending !== false)
      writer.tag(4, WireType.Varint).bool(message.pending);
    /* bool broken = 5; */
    if (message.broken !== false)
      writer.tag(5, WireType.Varint).bool(message.broken);
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Stats
 */
export const Stats = new Stats$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Row$Type extends MessageType<Row> {
  constructor() {
    super('Row', [
      { no: 1, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      { no: 2, name: 'id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 3,
        name: 'results',
        kind: 'scalar',
        repeat: 1 /*RepeatType.PACKED*/,
        T: 5 /*ScalarType.INT32*/,
      },
      {
        no: 4,
        name: 'cell_ids',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 5,
        name: 'messages',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 7,
        name: 'metric',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 8,
        name: 'metrics',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => Metric,
      },
      {
        no: 9,
        name: 'icons',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 10,
        name: 'issues',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      { no: 11, name: 'alert_info', kind: 'message', T: () => AlertInfo },
      {
        no: 12,
        name: 'user_property',
        kind: 'scalar',
        repeat: 2 /*RepeatType.UNPACKED*/,
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 13,
        name: 'properties',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => Property,
      },
    ]);
  }
  create(value?: PartialMessage<Row>): Row {
    const message = {
      name: '',
      id: '',
      results: [],
      cellIds: [],
      messages: [],
      metric: [],
      metrics: [],
      icons: [],
      issues: [],
      userProperty: [],
      properties: [],
    };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined) reflectionMergePartial<Row>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Row
  ): Row {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* string name */ 1:
          message.name = reader.string();
          break;
        case /* string id */ 2:
          message.id = reader.string();
          break;
        case /* repeated int32 results */ 3:
          if (wireType === WireType.LengthDelimited)
            for (let e = reader.int32() + reader.pos; reader.pos < e; )
              message.results.push(reader.int32());
          else message.results.push(reader.int32());
          break;
        case /* repeated string cell_ids */ 4:
          message.cellIds.push(reader.string());
          break;
        case /* repeated string messages */ 5:
          message.messages.push(reader.string());
          break;
        case /* repeated string metric */ 7:
          message.metric.push(reader.string());
          break;
        case /* repeated Metric metrics */ 8:
          message.metrics.push(
            Metric.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        case /* repeated string icons */ 9:
          message.icons.push(reader.string());
          break;
        case /* repeated string issues */ 10:
          message.issues.push(reader.string());
          break;
        case /* AlertInfo alert_info */ 11:
          message.alertInfo = AlertInfo.internalBinaryRead(
            reader,
            reader.uint32(),
            options,
            message.alertInfo
          );
          break;
        case /* repeated string user_property */ 12:
          message.userProperty.push(reader.string());
          break;
        case /* repeated Property properties */ 13:
          message.properties.push(
            Property.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: Row,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* string name = 1; */
    if (message.name !== '')
      writer.tag(1, WireType.LengthDelimited).string(message.name);
    /* string id = 2; */
    if (message.id !== '')
      writer.tag(2, WireType.LengthDelimited).string(message.id);
    /* repeated int32 results = 3; */
    if (message.results.length) {
      writer.tag(3, WireType.LengthDelimited).fork();
      for (let i = 0; i < message.results.length; i++)
        writer.int32(message.results[i]);
      writer.join();
    }
    /* repeated string cell_ids = 4; */
    for (let i = 0; i < message.cellIds.length; i++)
      writer.tag(4, WireType.LengthDelimited).string(message.cellIds[i]);
    /* repeated string messages = 5; */
    for (let i = 0; i < message.messages.length; i++)
      writer.tag(5, WireType.LengthDelimited).string(message.messages[i]);
    /* repeated string metric = 7; */
    for (let i = 0; i < message.metric.length; i++)
      writer.tag(7, WireType.LengthDelimited).string(message.metric[i]);
    /* repeated Metric metrics = 8; */
    for (let i = 0; i < message.metrics.length; i++)
      Metric.internalBinaryWrite(
        message.metrics[i],
        writer.tag(8, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* repeated string icons = 9; */
    for (let i = 0; i < message.icons.length; i++)
      writer.tag(9, WireType.LengthDelimited).string(message.icons[i]);
    /* repeated string issues = 10; */
    for (let i = 0; i < message.issues.length; i++)
      writer.tag(10, WireType.LengthDelimited).string(message.issues[i]);
    /* AlertInfo alert_info = 11; */
    if (message.alertInfo)
      AlertInfo.internalBinaryWrite(
        message.alertInfo,
        writer.tag(11, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* repeated string user_property = 12; */
    for (let i = 0; i < message.userProperty.length; i++)
      writer.tag(12, WireType.LengthDelimited).string(message.userProperty[i]);
    /* repeated Property properties = 13; */
    for (let i = 0; i < message.properties.length; i++)
      Property.internalBinaryWrite(
        message.properties[i],
        writer.tag(13, WireType.LengthDelimited).fork(),
        options
      ).join();
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Row
 */
export const Row = new Row$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Grid$Type extends MessageType<Grid> {
  constructor() {
    super('Grid', [
      {
        no: 1,
        name: 'columns',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => Column,
      },
      {
        no: 2,
        name: 'rows',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => Row,
      },
      { no: 4, name: 'config', kind: 'message', T: () => TestGroup },
      {
        no: 6,
        name: 'last_time_updated',
        kind: 'scalar',
        T: 1 /*ScalarType.DOUBLE*/,
      },
      {
        no: 8,
        name: 'update_info',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => UpdateInfo,
      },
      {
        no: 9,
        name: 'test_metadata',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => TestMetadata,
      },
      {
        no: 10,
        name: 'cluster',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => Cluster,
      },
      {
        no: 11,
        name: 'most_recent_cluster_timestamp',
        kind: 'scalar',
        T: 1 /*ScalarType.DOUBLE*/,
      },
    ]);
  }
  create(value?: PartialMessage<Grid>): Grid {
    const message = {
      columns: [],
      rows: [],
      lastTimeUpdated: 0,
      updateInfo: [],
      testMetadata: [],
      cluster: [],
      mostRecentClusterTimestamp: 0,
    };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined) reflectionMergePartial<Grid>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Grid
  ): Grid {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* repeated Column columns */ 1:
          message.columns.push(
            Column.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        case /* repeated Row rows */ 2:
          message.rows.push(
            Row.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        case /* TestGroup config */ 4:
          message.config = TestGroup.internalBinaryRead(
            reader,
            reader.uint32(),
            options,
            message.config
          );
          break;
        case /* double last_time_updated */ 6:
          message.lastTimeUpdated = reader.double();
          break;
        case /* repeated UpdateInfo update_info */ 8:
          message.updateInfo.push(
            UpdateInfo.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        case /* repeated TestMetadata test_metadata */ 9:
          message.testMetadata.push(
            TestMetadata.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        case /* repeated Cluster cluster */ 10:
          message.cluster.push(
            Cluster.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        case /* double most_recent_cluster_timestamp */ 11:
          message.mostRecentClusterTimestamp = reader.double();
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: Grid,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* repeated Column columns = 1; */
    for (let i = 0; i < message.columns.length; i++)
      Column.internalBinaryWrite(
        message.columns[i],
        writer.tag(1, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* repeated Row rows = 2; */
    for (let i = 0; i < message.rows.length; i++)
      Row.internalBinaryWrite(
        message.rows[i],
        writer.tag(2, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* TestGroup config = 4; */
    if (message.config)
      TestGroup.internalBinaryWrite(
        message.config,
        writer.tag(4, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* double last_time_updated = 6; */
    if (message.lastTimeUpdated !== 0)
      writer.tag(6, WireType.Bit64).double(message.lastTimeUpdated);
    /* repeated UpdateInfo update_info = 8; */
    for (let i = 0; i < message.updateInfo.length; i++)
      UpdateInfo.internalBinaryWrite(
        message.updateInfo[i],
        writer.tag(8, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* repeated TestMetadata test_metadata = 9; */
    for (let i = 0; i < message.testMetadata.length; i++)
      TestMetadata.internalBinaryWrite(
        message.testMetadata[i],
        writer.tag(9, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* repeated Cluster cluster = 10; */
    for (let i = 0; i < message.cluster.length; i++)
      Cluster.internalBinaryWrite(
        message.cluster[i],
        writer.tag(10, WireType.LengthDelimited).fork(),
        options
      ).join();
    /* double most_recent_cluster_timestamp = 11; */
    if (message.mostRecentClusterTimestamp !== 0)
      writer.tag(11, WireType.Bit64).double(message.mostRecentClusterTimestamp);
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Grid
 */
export const Grid = new Grid$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Cluster$Type extends MessageType<Cluster> {
  constructor() {
    super('Cluster', [
      { no: 1, name: 'test_status', kind: 'scalar', T: 5 /*ScalarType.INT32*/ },
      { no: 2, name: 'message', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
      {
        no: 3,
        name: 'cluster_row',
        kind: 'message',
        repeat: 1 /*RepeatType.PACKED*/,
        T: () => ClusterRow,
      },
    ]);
  }
  create(value?: PartialMessage<Cluster>): Cluster {
    const message = { testStatus: 0, message: '', clusterRow: [] };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<Cluster>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: Cluster
  ): Cluster {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* int32 test_status */ 1:
          message.testStatus = reader.int32();
          break;
        case /* string message */ 2:
          message.message = reader.string();
          break;
        case /* repeated ClusterRow cluster_row */ 3:
          message.clusterRow.push(
            ClusterRow.internalBinaryRead(reader, reader.uint32(), options)
          );
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: Cluster,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* int32 test_status = 1; */
    if (message.testStatus !== 0)
      writer.tag(1, WireType.Varint).int32(message.testStatus);
    /* string message = 2; */
    if (message.message !== '')
      writer.tag(2, WireType.LengthDelimited).string(message.message);
    /* repeated ClusterRow cluster_row = 3; */
    for (let i = 0; i < message.clusterRow.length; i++)
      ClusterRow.internalBinaryWrite(
        message.clusterRow[i],
        writer.tag(3, WireType.LengthDelimited).fork(),
        options
      ).join();
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message Cluster
 */
export const Cluster = new Cluster$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ClusterRow$Type extends MessageType<ClusterRow> {
  constructor() {
    super('ClusterRow', [
      {
        no: 1,
        name: 'display_name',
        kind: 'scalar',
        T: 9 /*ScalarType.STRING*/,
      },
      {
        no: 2,
        name: 'index',
        kind: 'scalar',
        repeat: 1 /*RepeatType.PACKED*/,
        T: 5 /*ScalarType.INT32*/,
      },
    ]);
  }
  create(value?: PartialMessage<ClusterRow>): ClusterRow {
    const message = { displayName: '', index: [] };
    globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
      enumerable: false,
      value: this,
    });
    if (value !== undefined)
      reflectionMergePartial<ClusterRow>(this, message, value);
    return message;
  }
  internalBinaryRead(
    reader: IBinaryReader,
    length: number,
    options: BinaryReadOptions,
    target?: ClusterRow
  ): ClusterRow {
    let message = target ?? this.create(),
      end = reader.pos + length;
    while (reader.pos < end) {
      let [fieldNo, wireType] = reader.tag();
      switch (fieldNo) {
        case /* string display_name */ 1:
          message.displayName = reader.string();
          break;
        case /* repeated int32 index */ 2:
          if (wireType === WireType.LengthDelimited)
            for (let e = reader.int32() + reader.pos; reader.pos < e; )
              message.index.push(reader.int32());
          else message.index.push(reader.int32());
          break;
        default:
          let u = options.readUnknownField;
          if (u === 'throw')
            throw new globalThis.Error(
              `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`
            );
          let d = reader.skip(wireType);
          if (u !== false)
            (u === true ? UnknownFieldHandler.onRead : u)(
              this.typeName,
              message,
              fieldNo,
              wireType,
              d
            );
      }
    }
    return message;
  }
  internalBinaryWrite(
    message: ClusterRow,
    writer: IBinaryWriter,
    options: BinaryWriteOptions
  ): IBinaryWriter {
    /* string display_name = 1; */
    if (message.displayName !== '')
      writer.tag(1, WireType.LengthDelimited).string(message.displayName);
    /* repeated int32 index = 2; */
    if (message.index.length) {
      writer.tag(2, WireType.LengthDelimited).fork();
      for (let i = 0; i < message.index.length; i++)
        writer.int32(message.index[i]);
      writer.join();
    }
    let u = options.writeUnknownFields;
    if (u !== false)
      (u == true ? UnknownFieldHandler.onWrite : u)(
        this.typeName,
        message,
        writer
      );
    return writer;
  }
}
/**
 * @generated MessageType for protobuf message ClusterRow
 */
export const ClusterRow = new ClusterRow$Type();
