Project import generated by Copybara

PiperOrigin-RevId: 298409332
pull/7266/head
Rafi Kamal 5 years ago committed by Copybara-Service
parent 4ff0fb841c
commit 64f151fa2b
  1. 178
      js/experimental/runtime/kernel/indexer.js

@ -47,118 +47,96 @@ function tagToFieldNumber(tag) {
}
/**
* An Indexer that indexes a given binary protobuf by fieldnumber.
* Creates an index of field locations in a given binary protobuf.
* @param {!BufferDecoder} bufferDecoder
* @param {number|undefined} pivot
* @return {!Storage<!Field>}
* @package
*/
class Indexer {
/**
* @param {!BufferDecoder} bufferDecoder
* @private
*/
constructor(bufferDecoder) {
/** @private @const {!BufferDecoder} */
this.bufferDecoder_ = bufferDecoder;
}
/**
* @param {number|undefined} pivot
* @return {!Storage<!Field>}
*/
index(pivot) {
this.bufferDecoder_.setCursor(this.bufferDecoder_.startIndex());
const storage = new Storage(pivot);
while (this.bufferDecoder_.hasNext()) {
const tag = this.bufferDecoder_.getUnsignedVarint32();
const wireType = tagToWireType(tag);
const fieldNumber = tagToFieldNumber(tag);
checkCriticalState(
fieldNumber > 0, `Invalid field number ${fieldNumber}`);
function buildIndex(bufferDecoder, pivot) {
bufferDecoder.setCursor(bufferDecoder.startIndex());
addIndexEntry(
storage, fieldNumber, wireType, this.bufferDecoder_.cursor());
const storage = new Storage(pivot);
while (bufferDecoder.hasNext()) {
const tag = bufferDecoder.getUnsignedVarint32();
const wireType = tagToWireType(tag);
const fieldNumber = tagToFieldNumber(tag);
checkCriticalState(fieldNumber > 0, `Invalid field number ${fieldNumber}`);
checkCriticalState(
!this.skipField_(wireType, fieldNumber),
'Found unmatched stop group.');
}
return storage;
}
addIndexEntry(storage, fieldNumber, wireType, bufferDecoder.cursor());
/**
* Skips over fields until the next field of the message.
* @param {!WireType} wireType
* @param {number} fieldNumber
* @return {boolean} Whether the field we skipped over was a stop group.
* @private
*/
skipField_(wireType, fieldNumber) {
switch (wireType) {
case WireType.VARINT:
checkCriticalElementIndex(
this.bufferDecoder_.cursor(), this.bufferDecoder_.endIndex());
this.bufferDecoder_.skipVarint(this.bufferDecoder_.cursor());
return false;
case WireType.FIXED64:
this.bufferDecoder_.skip(8);
return false;
case WireType.DELIMITED:
checkCriticalElementIndex(
this.bufferDecoder_.cursor(), this.bufferDecoder_.endIndex());
const length = this.bufferDecoder_.getUnsignedVarint32();
this.bufferDecoder_.skip(length);
return false;
case WireType.START_GROUP:
checkCriticalState(this.skipGroup_(fieldNumber), 'No end group found.');
return false;
case WireType.END_GROUP:
// Signal that we found a stop group to the caller
return true;
case WireType.FIXED32:
this.bufferDecoder_.skip(4);
return false;
default:
throw new Error(`Invalid wire type: ${wireType}`);
}
checkCriticalState(
!skipField_(bufferDecoder, wireType, fieldNumber),
'Found unmatched stop group.');
}
return storage;
}
/**
* Skips over fields until it finds the end of a given group.
* @param {number} groupFieldNumber
* @return {boolean} Returns true if an end was found.
* @private
*/
skipGroup_(groupFieldNumber) {
// On a start group we need to keep skipping fields until we find a
// corresponding stop group
// Note: Since we are calling skipField from here nested groups will be
// handled by recursion of this method and thus we will not see a nested
// STOP GROUP here unless there is something wrong with the input data.
while (this.bufferDecoder_.hasNext()) {
const tag = this.bufferDecoder_.getUnsignedVarint32();
const wireType = tagToWireType(tag);
const fieldNumber = tagToFieldNumber(tag);
if (this.skipField_(wireType, fieldNumber)) {
checkCriticalState(
groupFieldNumber === fieldNumber,
`Expected stop group for fieldnumber ${
groupFieldNumber} not found.`);
return true;
}
}
return false;
/**
* Skips over fields until the next field of the message.
* @param {!BufferDecoder} bufferDecoder
* @param {!WireType} wireType
* @param {number} fieldNumber
* @return {boolean} Whether the field we skipped over was a stop group.
* @private
*/
function skipField_(bufferDecoder, wireType, fieldNumber) {
switch (wireType) {
case WireType.VARINT:
checkCriticalElementIndex(
bufferDecoder.cursor(), bufferDecoder.endIndex());
bufferDecoder.skipVarint(bufferDecoder.cursor());
return false;
case WireType.FIXED64:
bufferDecoder.skip(8);
return false;
case WireType.DELIMITED:
checkCriticalElementIndex(
bufferDecoder.cursor(), bufferDecoder.endIndex());
const length = bufferDecoder.getUnsignedVarint32();
bufferDecoder.skip(length);
return false;
case WireType.START_GROUP:
checkCriticalState(
skipGroup_(bufferDecoder, fieldNumber), 'No end group found.');
return false;
case WireType.END_GROUP:
// Signal that we found a stop group to the caller
return true;
case WireType.FIXED32:
bufferDecoder.skip(4);
return false;
default:
throw new Error(`Invalid wire type: ${wireType}`);
}
}
/**
* Creates an index of field locations in a given binary protobuf.
* Skips over fields until it finds the end of a given group.
* @param {!BufferDecoder} bufferDecoder
* @param {number|undefined} pivot
* @return {!Storage<!Field>}
* @package
* @param {number} groupFieldNumber
* @return {boolean} Returns true if an end was found.
* @private
*/
function buildIndex(bufferDecoder, pivot) {
return new Indexer(bufferDecoder).index(pivot);
function skipGroup_(bufferDecoder, groupFieldNumber) {
// On a start group we need to keep skipping fields until we find a
// corresponding stop group
// Note: Since we are calling skipField from here nested groups will be
// handled by recursion of this method and thus we will not see a nested
// STOP GROUP here unless there is something wrong with the input data.
while (bufferDecoder.hasNext()) {
const tag = bufferDecoder.getUnsignedVarint32();
const wireType = tagToWireType(tag);
const fieldNumber = tagToFieldNumber(tag);
if (skipField_(bufferDecoder, wireType, fieldNumber)) {
checkCriticalState(
groupFieldNumber === fieldNumber,
`Expected stop group for fieldnumber ${groupFieldNumber} not found.`);
return true;
}
}
return false;
}
exports = {

Loading…
Cancel
Save