• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Utilities to index a binary proto by fieldnumbers without
3 * relying on strutural proto information.
4 */
5goog.module('protobuf.binary.indexer');
6
7const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
8const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
9const WireType = goog.require('protobuf.binary.WireType');
10const {Field} = goog.require('protobuf.binary.field');
11const {checkCriticalState} = goog.require('protobuf.internal.checks');
12const {skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag');
13
14/**
15 * Appends a new entry in the index array for the given field number.
16 * @param {!BinaryStorage<!Field>} storage
17 * @param {number} fieldNumber
18 * @param {!WireType} wireType
19 * @param {number} startIndex
20 */
21function addIndexEntry(storage, fieldNumber, wireType, startIndex) {
22  const field = storage.get(fieldNumber);
23  if (field !== undefined) {
24    field.addIndexEntry(wireType, startIndex);
25  } else {
26    storage.set(fieldNumber, Field.fromFirstIndexEntry(wireType, startIndex));
27  }
28}
29
30/**
31 * Creates an index of field locations in a given binary protobuf.
32 * @param {!BufferDecoder} bufferDecoder
33 * @param {number|undefined} pivot
34 * @return {!BinaryStorage<!Field>}
35 * @package
36 */
37function buildIndex(bufferDecoder, pivot) {
38  bufferDecoder.setCursor(bufferDecoder.startIndex());
39
40  const storage = new BinaryStorage(pivot);
41  while (bufferDecoder.hasNext()) {
42    const tag = bufferDecoder.getUnsignedVarint32();
43    const wireType = tagToWireType(tag);
44    const fieldNumber = tagToFieldNumber(tag);
45    checkCriticalState(fieldNumber > 0, `Invalid field number ${fieldNumber}`);
46    addIndexEntry(storage, fieldNumber, wireType, bufferDecoder.cursor());
47    skipField(bufferDecoder, wireType, fieldNumber);
48  }
49  return storage;
50}
51
52exports = {
53  buildIndex,
54  tagToWireType,
55};
56