Add dependencies locally
This commit is contained in:
130
deps/protobuf/js/experimental/runtime/kernel/binary_storage.js
vendored
Normal file
130
deps/protobuf/js/experimental/runtime/kernel/binary_storage.js
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
goog.module('protobuf.runtime.BinaryStorage');
|
||||
|
||||
const Storage = goog.require('protobuf.runtime.Storage');
|
||||
const {checkDefAndNotNull} = goog.require('protobuf.internal.checks');
|
||||
|
||||
/**
|
||||
* Class storing all the fields of a binary protobuf message.
|
||||
*
|
||||
* @package
|
||||
* @template FieldType
|
||||
* @implements {Storage}
|
||||
*/
|
||||
class BinaryStorage {
|
||||
/**
|
||||
* @param {number=} pivot
|
||||
*/
|
||||
constructor(pivot = Storage.DEFAULT_PIVOT) {
|
||||
/**
|
||||
* Fields having a field number no greater than the pivot value are stored
|
||||
* into an array for fast access. A field with field number X is stored into
|
||||
* the array position X - 1.
|
||||
*
|
||||
* @private @const {!Array<!FieldType|undefined>}
|
||||
*/
|
||||
this.array_ = new Array(pivot);
|
||||
|
||||
/**
|
||||
* Fields having a field number higher than the pivot value are stored into
|
||||
* the map. We create the map only when it's needed, since even an empty map
|
||||
* takes up a significant amount of memory.
|
||||
*
|
||||
* @private {?Map<number, !FieldType>}
|
||||
*/
|
||||
this.map_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fields having a field number no greater than the pivot value are stored
|
||||
* into an array for fast access. A field with field number X is stored into
|
||||
* the array position X - 1.
|
||||
* @return {number}
|
||||
* @override
|
||||
*/
|
||||
getPivot() {
|
||||
return this.array_.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a field in the specified field number.
|
||||
*
|
||||
* @param {number} fieldNumber
|
||||
* @param {!FieldType} field
|
||||
* @override
|
||||
*/
|
||||
set(fieldNumber, field) {
|
||||
if (fieldNumber <= this.getPivot()) {
|
||||
this.array_[fieldNumber - 1] = field;
|
||||
} else {
|
||||
if (this.map_) {
|
||||
this.map_.set(fieldNumber, field);
|
||||
} else {
|
||||
this.map_ = new Map([[fieldNumber, field]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a field at the specified field number.
|
||||
*
|
||||
* @param {number} fieldNumber
|
||||
* @return {!FieldType|undefined}
|
||||
* @override
|
||||
*/
|
||||
get(fieldNumber) {
|
||||
if (fieldNumber <= this.getPivot()) {
|
||||
return this.array_[fieldNumber - 1];
|
||||
} else {
|
||||
return this.map_ ? this.map_.get(fieldNumber) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a field from the specified field number.
|
||||
*
|
||||
* @param {number} fieldNumber
|
||||
* @override
|
||||
*/
|
||||
delete(fieldNumber) {
|
||||
if (fieldNumber <= this.getPivot()) {
|
||||
delete this.array_[fieldNumber - 1];
|
||||
} else {
|
||||
if (this.map_) {
|
||||
this.map_.delete(fieldNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the provided function once for each field.
|
||||
*
|
||||
* @param {function(!FieldType, number): void} callback
|
||||
* @override
|
||||
*/
|
||||
forEach(callback) {
|
||||
this.array_.forEach((field, fieldNumber) => {
|
||||
if (field) {
|
||||
callback(checkDefAndNotNull(field), fieldNumber + 1);
|
||||
}
|
||||
});
|
||||
if (this.map_) {
|
||||
this.map_.forEach(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shallow copy of the storage.
|
||||
*
|
||||
* @return {!BinaryStorage}
|
||||
* @override
|
||||
*/
|
||||
shallowCopy() {
|
||||
const copy = new BinaryStorage(this.getPivot());
|
||||
this.forEach(
|
||||
(field, fieldNumber) =>
|
||||
void copy.set(fieldNumber, field.shallowCopy()));
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
exports = BinaryStorage;
|
165
deps/protobuf/js/experimental/runtime/kernel/binary_storage_test.js
vendored
Normal file
165
deps/protobuf/js/experimental/runtime/kernel/binary_storage_test.js
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* @fileoverview Tests for storage.js.
|
||||
*/
|
||||
goog.module('protobuf.runtime.BinaryStorageTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
|
||||
const {Field} = goog.require('protobuf.binary.field');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
const DEFAULT_PIVOT = 24;
|
||||
|
||||
const /** !Field */ field1 =
|
||||
Field.fromDecodedValue(/* decodedValue= */ 1, /* encoder= */ () => {});
|
||||
const /** !Field */ field2 =
|
||||
Field.fromDecodedValue(/* decodedValue= */ 2, /* encoder= */ () => {});
|
||||
const /** !Field */ field3 =
|
||||
Field.fromDecodedValue(/* decodedValue= */ 3, /* encoder= */ () => {});
|
||||
const /** !Field */ field4 =
|
||||
Field.fromDecodedValue(/* decodedValue= */ 4, /* encoder= */ () => {});
|
||||
|
||||
/**
|
||||
* Returns the number of fields stored.
|
||||
*
|
||||
* @param {!BinaryStorage} storage
|
||||
* @return {number}
|
||||
*/
|
||||
function getStorageSize(storage) {
|
||||
let size = 0;
|
||||
storage.forEach(() => void size++);
|
||||
return size;
|
||||
}
|
||||
|
||||
describe('BinaryStorage', () => {
|
||||
it('sets and gets a field not greater than the pivot', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
|
||||
storage.set(1, field1);
|
||||
storage.set(DEFAULT_PIVOT, field2);
|
||||
|
||||
expect(storage.getPivot()).toBe(DEFAULT_PIVOT);
|
||||
expect(storage.get(1)).toBe(field1);
|
||||
expect(storage.get(DEFAULT_PIVOT)).toBe(field2);
|
||||
});
|
||||
|
||||
it('sets and gets a field greater than the pivot', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
|
||||
storage.set(DEFAULT_PIVOT + 1, field1);
|
||||
storage.set(100000, field2);
|
||||
|
||||
expect(storage.get(DEFAULT_PIVOT + 1)).toBe(field1);
|
||||
expect(storage.get(100000)).toBe(field2);
|
||||
});
|
||||
|
||||
it('sets and gets a field when pivot is zero', () => {
|
||||
const storage = new BinaryStorage(0);
|
||||
|
||||
storage.set(0, field1);
|
||||
storage.set(100000, field2);
|
||||
|
||||
expect(storage.getPivot()).toBe(0);
|
||||
expect(storage.get(0)).toBe(field1);
|
||||
expect(storage.get(100000)).toBe(field2);
|
||||
});
|
||||
|
||||
it('sets and gets a field when pivot is undefined', () => {
|
||||
const storage = new BinaryStorage();
|
||||
|
||||
storage.set(0, field1);
|
||||
storage.set(DEFAULT_PIVOT, field2);
|
||||
storage.set(DEFAULT_PIVOT + 1, field3);
|
||||
|
||||
expect(storage.getPivot()).toBe(DEFAULT_PIVOT);
|
||||
expect(storage.get(0)).toBe(field1);
|
||||
expect(storage.get(DEFAULT_PIVOT)).toBe(field2);
|
||||
expect(storage.get(DEFAULT_PIVOT + 1)).toBe(field3);
|
||||
});
|
||||
|
||||
it('returns undefined for nonexistent fields', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
|
||||
expect(storage.get(1)).toBeUndefined();
|
||||
expect(storage.get(DEFAULT_PIVOT)).toBeUndefined();
|
||||
expect(storage.get(DEFAULT_PIVOT + 1)).toBeUndefined();
|
||||
expect(storage.get(100000)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns undefined for nonexistent fields after map initialization',
|
||||
() => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
storage.set(100001, field1);
|
||||
|
||||
expect(storage.get(1)).toBeUndefined();
|
||||
expect(storage.get(DEFAULT_PIVOT)).toBeUndefined();
|
||||
expect(storage.get(DEFAULT_PIVOT + 1)).toBeUndefined();
|
||||
expect(storage.get(100000)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('deletes a field in delete() when values are only in array', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
storage.set(1, field1);
|
||||
|
||||
storage.delete(1);
|
||||
|
||||
expect(storage.get(1)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('deletes a field in delete() when values are both in array and map',
|
||||
() => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
storage.set(DEFAULT_PIVOT, field2);
|
||||
storage.set(DEFAULT_PIVOT + 1, field3);
|
||||
|
||||
storage.delete(DEFAULT_PIVOT);
|
||||
storage.delete(DEFAULT_PIVOT + 1);
|
||||
|
||||
expect(storage.get(DEFAULT_PIVOT)).toBeUndefined();
|
||||
expect(storage.get(DEFAULT_PIVOT + 1)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('deletes a field in delete() when values are only in map', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
storage.set(100000, field4);
|
||||
|
||||
storage.delete(100000);
|
||||
|
||||
expect(storage.get(100000)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('loops over all the elements in forEach()', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
storage.set(1, field1);
|
||||
storage.set(DEFAULT_PIVOT, field2);
|
||||
storage.set(DEFAULT_PIVOT + 1, field3);
|
||||
storage.set(100000, field4);
|
||||
|
||||
const fields = new Map();
|
||||
storage.forEach(
|
||||
(field, fieldNumber) => void fields.set(fieldNumber, field));
|
||||
|
||||
expect(fields.size).toEqual(4);
|
||||
expect(fields.get(1)).toBe(field1);
|
||||
expect(storage.get(DEFAULT_PIVOT)).toBe(field2);
|
||||
expect(storage.get(DEFAULT_PIVOT + 1)).toBe(field3);
|
||||
expect(fields.get(100000)).toBe(field4);
|
||||
});
|
||||
|
||||
it('creates a shallow copy of the storage in shallowCopy()', () => {
|
||||
const storage = new BinaryStorage(DEFAULT_PIVOT);
|
||||
storage.set(1, field1);
|
||||
storage.set(100000, field2);
|
||||
|
||||
const copy = storage.shallowCopy();
|
||||
|
||||
expect(getStorageSize(copy)).toEqual(2);
|
||||
expect(copy.get(1)).not.toBe(field1);
|
||||
expect(copy.get(1).getDecodedValue()).toEqual(1);
|
||||
expect(copy.get(100000)).not.toBe(field1);
|
||||
expect(copy.get(100000).getDecodedValue()).toEqual(2);
|
||||
});
|
||||
});
|
79
deps/protobuf/js/experimental/runtime/kernel/bool_test_pairs.js
vendored
Normal file
79
deps/protobuf/js/experimental/runtime/kernel/bool_test_pairs.js
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @fileoverview Test data for bool encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.boolTestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of boolean values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, boolValue: boolean, bufferDecoder:
|
||||
* !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getBoolPairs() {
|
||||
const boolPairs = [
|
||||
{
|
||||
name: 'true',
|
||||
boolValue: true,
|
||||
bufferDecoder: createBufferDecoder(0x01),
|
||||
},
|
||||
{
|
||||
name: 'false',
|
||||
boolValue: false,
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
},
|
||||
{
|
||||
name: 'two-byte true',
|
||||
boolValue: true,
|
||||
bufferDecoder: createBufferDecoder(0x80, 0x01),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'two-byte false',
|
||||
boolValue: false,
|
||||
bufferDecoder: createBufferDecoder(0x80, 0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
boolValue: true,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'max signed int 2^63 - 1',
|
||||
boolValue: true,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'min signed int -2^63',
|
||||
boolValue: true,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'overflowed but valid varint',
|
||||
boolValue: false,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'errors out for 11 bytes',
|
||||
boolValue: true,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
|
||||
error: true,
|
||||
skip_writer: true,
|
||||
},
|
||||
];
|
||||
return [...boolPairs];
|
||||
}
|
||||
|
||||
exports = {getBoolPairs};
|
343
deps/protobuf/js/experimental/runtime/kernel/buffer_decoder.js
vendored
Normal file
343
deps/protobuf/js/experimental/runtime/kernel/buffer_decoder.js
vendored
Normal file
@ -0,0 +1,343 @@
|
||||
/**
|
||||
* @fileoverview A buffer implementation that can decode data for protobufs.
|
||||
*/
|
||||
|
||||
goog.module('protobuf.binary.BufferDecoder');
|
||||
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const functions = goog.require('goog.functions');
|
||||
const {POLYFILL_TEXT_ENCODING, checkCriticalPositionIndex, checkCriticalState, checkState} = goog.require('protobuf.internal.checks');
|
||||
const {byteStringFromUint8ArrayUnsafe} = goog.require('protobuf.byteStringInternal');
|
||||
const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays');
|
||||
const {decode} = goog.require('protobuf.binary.textencoding');
|
||||
|
||||
/**
|
||||
* Returns a valid utf-8 decoder function based on TextDecoder if available or
|
||||
* a polyfill.
|
||||
* Some of the environments we run in do not have TextDecoder defined.
|
||||
* TextDecoder is faster than our polyfill so we prefer it over the polyfill.
|
||||
* @return {function(!DataView): string}
|
||||
*/
|
||||
function getStringDecoderFunction() {
|
||||
if (goog.global['TextDecoder']) {
|
||||
const textDecoder = new goog.global['TextDecoder']('utf-8', {fatal: true});
|
||||
return bytes => textDecoder.decode(bytes);
|
||||
}
|
||||
if (POLYFILL_TEXT_ENCODING) {
|
||||
return decode;
|
||||
} else {
|
||||
throw new Error(
|
||||
'TextDecoder is missing. ' +
|
||||
'Enable protobuf.defines.POLYFILL_TEXT_ENCODING.');
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {function(): function(!DataView): string} */
|
||||
const stringDecoderFunction =
|
||||
functions.cacheReturnValue(() => getStringDecoderFunction());
|
||||
|
||||
/** @type {function(): !DataView} */
|
||||
const emptyDataView =
|
||||
functions.cacheReturnValue(() => new DataView(new ArrayBuffer(0)));
|
||||
|
||||
class BufferDecoder {
|
||||
/**
|
||||
* @param {!Array<!BufferDecoder>} bufferDecoders
|
||||
* @return {!BufferDecoder}
|
||||
*/
|
||||
static merge(bufferDecoders) {
|
||||
const uint8Arrays = bufferDecoders.map(b => b.asUint8Array());
|
||||
const bytesArray = concatenateByteArrays(uint8Arrays);
|
||||
return BufferDecoder.fromArrayBuffer(bytesArray.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!ArrayBuffer} arrayBuffer
|
||||
* @return {!BufferDecoder}
|
||||
*/
|
||||
static fromArrayBuffer(arrayBuffer) {
|
||||
return new BufferDecoder(
|
||||
new DataView(arrayBuffer), 0, arrayBuffer.byteLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!DataView} dataView
|
||||
* @param {number} startIndex
|
||||
* @param {number} length
|
||||
* @private
|
||||
*/
|
||||
constructor(dataView, startIndex, length) {
|
||||
/** @private @const {!DataView} */
|
||||
this.dataView_ = dataView;
|
||||
/** @private @const {number} */
|
||||
this.startIndex_ = startIndex;
|
||||
/** @private @const {number} */
|
||||
this.endIndex_ = startIndex + length;
|
||||
/** @private {number} */
|
||||
this.cursor_ = startIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start index of the underlying buffer.
|
||||
* @return {number}
|
||||
*/
|
||||
startIndex() {
|
||||
return this.startIndex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end index of the underlying buffer.
|
||||
* @return {number}
|
||||
*/
|
||||
endIndex() {
|
||||
return this.endIndex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the underlying buffer.
|
||||
* @return {number}
|
||||
*/
|
||||
length() {
|
||||
return this.endIndex_ - this.startIndex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start position of the next data, i.e. end position of the last
|
||||
* read data + 1.
|
||||
* @return {number}
|
||||
*/
|
||||
cursor() {
|
||||
return this.cursor_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cursor to the specified position.
|
||||
* @param {number} position
|
||||
*/
|
||||
setCursor(position) {
|
||||
this.cursor_ = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if there is more data to read after the current cursor position.
|
||||
* @return {boolean}
|
||||
*/
|
||||
hasNext() {
|
||||
return this.cursor_ < this.endIndex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a float32 from a given index
|
||||
* @param {number} index
|
||||
* @return {number}
|
||||
*/
|
||||
getFloat32(index) {
|
||||
this.cursor_ = index + 4;
|
||||
return this.dataView_.getFloat32(index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a float64 from a given index
|
||||
* @param {number} index
|
||||
* @return {number}
|
||||
*/
|
||||
getFloat64(index) {
|
||||
this.cursor_ = index + 8;
|
||||
return this.dataView_.getFloat64(index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int32 from a given index
|
||||
* @param {number} index
|
||||
* @return {number}
|
||||
*/
|
||||
getInt32(index) {
|
||||
this.cursor_ = index + 4;
|
||||
return this.dataView_.getInt32(index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a uint32 from a given index
|
||||
* @param {number} index
|
||||
* @return {number}
|
||||
*/
|
||||
getUint32(index) {
|
||||
this.cursor_ = index + 4;
|
||||
return this.dataView_.getUint32(index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns two JS numbers each representing 32 bits of a 64 bit number. Also
|
||||
* sets the cursor to the start of the next block of data.
|
||||
* @param {number} index
|
||||
* @return {{lowBits: number, highBits: number}}
|
||||
*/
|
||||
getVarint(index) {
|
||||
this.cursor_ = index;
|
||||
let lowBits = 0;
|
||||
let highBits = 0;
|
||||
|
||||
for (let shift = 0; shift < 28; shift += 7) {
|
||||
const b = this.dataView_.getUint8(this.cursor_++);
|
||||
lowBits |= (b & 0x7F) << shift;
|
||||
if ((b & 0x80) === 0) {
|
||||
return {lowBits, highBits};
|
||||
}
|
||||
}
|
||||
|
||||
const middleByte = this.dataView_.getUint8(this.cursor_++);
|
||||
|
||||
// last four bits of the first 32 bit number
|
||||
lowBits |= (middleByte & 0x0F) << 28;
|
||||
|
||||
// 3 upper bits are part of the next 32 bit number
|
||||
highBits = (middleByte & 0x70) >> 4;
|
||||
|
||||
if ((middleByte & 0x80) === 0) {
|
||||
return {lowBits, highBits};
|
||||
}
|
||||
|
||||
|
||||
for (let shift = 3; shift <= 31; shift += 7) {
|
||||
const b = this.dataView_.getUint8(this.cursor_++);
|
||||
highBits |= (b & 0x7F) << shift;
|
||||
if ((b & 0x80) === 0) {
|
||||
return {lowBits, highBits};
|
||||
}
|
||||
}
|
||||
|
||||
checkCriticalState(false, 'Data is longer than 10 bytes');
|
||||
|
||||
return {lowBits, highBits};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unsigned int32 number at the current cursor position. The upper
|
||||
* bits are discarded if the varint is longer than 32 bits. Also sets the
|
||||
* cursor to the start of the next block of data.
|
||||
* @return {number}
|
||||
*/
|
||||
getUnsignedVarint32() {
|
||||
let b = this.dataView_.getUint8(this.cursor_++);
|
||||
let result = b & 0x7F;
|
||||
if ((b & 0x80) === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
b = this.dataView_.getUint8(this.cursor_++);
|
||||
result |= (b & 0x7F) << 7;
|
||||
if ((b & 0x80) === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
b = this.dataView_.getUint8(this.cursor_++);
|
||||
result |= (b & 0x7F) << 14;
|
||||
if ((b & 0x80) === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
b = this.dataView_.getUint8(this.cursor_++);
|
||||
result |= (b & 0x7F) << 21;
|
||||
if ((b & 0x80) === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Extract only last 4 bits
|
||||
b = this.dataView_.getUint8(this.cursor_++);
|
||||
result |= (b & 0x0F) << 28;
|
||||
|
||||
for (let readBytes = 5; ((b & 0x80) !== 0) && readBytes < 10; readBytes++) {
|
||||
b = this.dataView_.getUint8(this.cursor_++);
|
||||
}
|
||||
|
||||
checkCriticalState((b & 0x80) === 0, 'Data is longer than 10 bytes');
|
||||
|
||||
// Result can be have 32 bits, convert it to unsigned
|
||||
return result >>> 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unsigned int32 number at the specified index. The upper bits are
|
||||
* discarded if the varint is longer than 32 bits. Also sets the cursor to the
|
||||
* start of the next block of data.
|
||||
* @param {number} index
|
||||
* @return {number}
|
||||
*/
|
||||
getUnsignedVarint32At(index) {
|
||||
this.cursor_ = index;
|
||||
return this.getUnsignedVarint32();
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeks forward by the given amount.
|
||||
* @param {number} skipAmount
|
||||
* @package
|
||||
*/
|
||||
skip(skipAmount) {
|
||||
this.cursor_ += skipAmount;
|
||||
checkCriticalPositionIndex(this.cursor_, this.endIndex_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips over a varint from the current cursor position.
|
||||
* @package
|
||||
*/
|
||||
skipVarint() {
|
||||
const startIndex = this.cursor_;
|
||||
while (this.dataView_.getUint8(this.cursor_++) & 0x80) {
|
||||
}
|
||||
checkCriticalPositionIndex(this.cursor_, startIndex + 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} startIndex
|
||||
* @param {number} length
|
||||
* @return {!BufferDecoder}
|
||||
*/
|
||||
subBufferDecoder(startIndex, length) {
|
||||
checkState(
|
||||
startIndex >= this.startIndex(),
|
||||
`Current start: ${this.startIndex()}, subBufferDecoder start: ${
|
||||
startIndex}`);
|
||||
checkState(length >= 0, `Length: ${length}`);
|
||||
checkState(
|
||||
startIndex + length <= this.endIndex(),
|
||||
`Current end: ${this.endIndex()}, subBufferDecoder start: ${
|
||||
startIndex}, subBufferDecoder length: ${length}`);
|
||||
return new BufferDecoder(this.dataView_, startIndex, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the buffer as a string.
|
||||
* @return {string}
|
||||
*/
|
||||
asString() {
|
||||
// TODO: Remove this check when we no longer need to support IE
|
||||
const stringDataView = this.length() === 0 ?
|
||||
emptyDataView() :
|
||||
new DataView(this.dataView_.buffer, this.startIndex_, this.length());
|
||||
return stringDecoderFunction()(stringDataView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the buffer as a ByteString.
|
||||
* @return {!ByteString}
|
||||
*/
|
||||
asByteString() {
|
||||
return byteStringFromUint8ArrayUnsafe(this.asUint8Array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DataView as an Uint8Array. DO NOT MODIFY or expose the
|
||||
* underlying buffer.
|
||||
*
|
||||
* @package
|
||||
* @return {!Uint8Array}
|
||||
*/
|
||||
asUint8Array() {
|
||||
return new Uint8Array(
|
||||
this.dataView_.buffer, this.startIndex_, this.length());
|
||||
}
|
||||
}
|
||||
|
||||
exports = BufferDecoder;
|
18
deps/protobuf/js/experimental/runtime/kernel/buffer_decoder_helper.js
vendored
Normal file
18
deps/protobuf/js/experimental/runtime/kernel/buffer_decoder_helper.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @fileoverview Helper methods to create BufferDecoders.
|
||||
*/
|
||||
goog.module('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
|
||||
/**
|
||||
* @param {...number} bytes
|
||||
* @return {!BufferDecoder}
|
||||
*/
|
||||
function createBufferDecoder(...bytes) {
|
||||
return BufferDecoder.fromArrayBuffer(new Uint8Array(bytes).buffer);
|
||||
}
|
||||
|
||||
exports = {
|
||||
createBufferDecoder,
|
||||
};
|
242
deps/protobuf/js/experimental/runtime/kernel/buffer_decoder_test.js
vendored
Normal file
242
deps/protobuf/js/experimental/runtime/kernel/buffer_decoder_test.js
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
/**
|
||||
* @fileoverview Tests for BufferDecoder.
|
||||
*/
|
||||
|
||||
goog.module('protobuf.binary.varintsTest');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {CHECK_CRITICAL_STATE, CHECK_STATE} = goog.require('protobuf.internal.checks');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
/**
|
||||
* @param {...number} bytes
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
function createArrayBuffer(...bytes) {
|
||||
return new Uint8Array(bytes).buffer;
|
||||
}
|
||||
|
||||
describe('setCursor does', () => {
|
||||
it('set the cursor at the position specified', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1));
|
||||
expect(bufferDecoder.cursor()).toBe(0);
|
||||
bufferDecoder.setCursor(1);
|
||||
expect(bufferDecoder.cursor()).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('skip does', () => {
|
||||
it('advance the cursor', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0, 0x1, 0x2));
|
||||
bufferDecoder.setCursor(1);
|
||||
bufferDecoder.skip(1);
|
||||
expect(bufferDecoder.cursor()).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Skip varint does', () => {
|
||||
it('skip a varint', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01));
|
||||
bufferDecoder.skipVarint();
|
||||
expect(bufferDecoder.cursor()).toBe(1);
|
||||
});
|
||||
|
||||
it('fail when varint is larger than 10 bytes', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00));
|
||||
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => bufferDecoder.skipVarint()).toThrow();
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
bufferDecoder.skipVarint();
|
||||
expect(bufferDecoder.cursor()).toBe(11);
|
||||
}
|
||||
});
|
||||
|
||||
it('fail when varint is beyond end of underlying array', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x80));
|
||||
expect(() => bufferDecoder.skipVarint()).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('readVarint64 does', () => {
|
||||
it('read zero', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00));
|
||||
const {lowBits, highBits} = bufferDecoder.getVarint(0);
|
||||
expect(lowBits).toBe(0);
|
||||
expect(highBits).toBe(0);
|
||||
expect(bufferDecoder.cursor()).toBe(1);
|
||||
});
|
||||
|
||||
it('read one', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01));
|
||||
const {lowBits, highBits} = bufferDecoder.getVarint(0);
|
||||
expect(lowBits).toBe(1);
|
||||
expect(highBits).toBe(0);
|
||||
expect(bufferDecoder.cursor()).toBe(1);
|
||||
});
|
||||
|
||||
it('read max value', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01));
|
||||
const {lowBits, highBits} = bufferDecoder.getVarint(0);
|
||||
expect(lowBits).toBe(-1);
|
||||
expect(highBits).toBe(-1);
|
||||
expect(bufferDecoder.cursor()).toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('readUnsignedVarint32 does', () => {
|
||||
it('read zero', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00));
|
||||
const result = bufferDecoder.getUnsignedVarint32();
|
||||
expect(result).toBe(0);
|
||||
expect(bufferDecoder.cursor()).toBe(1);
|
||||
});
|
||||
|
||||
it('read one', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01));
|
||||
const result = bufferDecoder.getUnsignedVarint32();
|
||||
expect(result).toBe(1);
|
||||
expect(bufferDecoder.cursor()).toBe(1);
|
||||
});
|
||||
|
||||
it('read max int32', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF, 0x0F));
|
||||
const result = bufferDecoder.getUnsignedVarint32();
|
||||
expect(result).toBe(4294967295);
|
||||
expect(bufferDecoder.cursor()).toBe(5);
|
||||
});
|
||||
|
||||
it('read max value', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01));
|
||||
const result = bufferDecoder.getUnsignedVarint32();
|
||||
expect(result).toBe(4294967295);
|
||||
expect(bufferDecoder.cursor()).toBe(10);
|
||||
});
|
||||
|
||||
it('fail if data is longer than 10 bytes', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(createArrayBuffer(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01));
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => bufferDecoder.getUnsignedVarint32()).toThrow();
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const result = bufferDecoder.getUnsignedVarint32();
|
||||
expect(result).toBe(4294967295);
|
||||
expect(bufferDecoder.cursor()).toBe(10);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('readUnsignedVarint32At does', () => {
|
||||
it('reads from a specific index', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x1, 0x2));
|
||||
const result = bufferDecoder.getUnsignedVarint32At(1);
|
||||
expect(result).toBe(2);
|
||||
expect(bufferDecoder.cursor()).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFloat32 does', () => {
|
||||
it('read one', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x00, 0x00, 0x80, 0x3F));
|
||||
const result = bufferDecoder.getFloat32(0);
|
||||
expect(result).toBe(1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFloat64 does', () => {
|
||||
it('read one', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F));
|
||||
const result = bufferDecoder.getFloat64(0);
|
||||
expect(result).toBe(1);
|
||||
expect(bufferDecoder.cursor()).toBe(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getInt32 does', () => {
|
||||
it('read one', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x01, 0x00, 0x00, 0x00));
|
||||
const result = bufferDecoder.getInt32(0);
|
||||
expect(result).toBe(1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
|
||||
it('read minus one', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF));
|
||||
const result = bufferDecoder.getInt32(0);
|
||||
expect(result).toBe(-1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUint32 does', () => {
|
||||
it('read one', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x00, 0x00, 0x0));
|
||||
const result = bufferDecoder.getUint32(0);
|
||||
expect(result).toBe(1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
|
||||
it('read max uint32', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0xFF, 0xFF, 0xFF, 0xFF));
|
||||
const result = bufferDecoder.getUint32(0);
|
||||
expect(result).toBe(4294967295);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('subBufferDecoder does', () => {
|
||||
it('can create valid sub buffers', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00, 0x01, 0x02));
|
||||
|
||||
expect(bufferDecoder.subBufferDecoder(0, 0))
|
||||
.toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer()));
|
||||
expect(bufferDecoder.subBufferDecoder(0, 1))
|
||||
.toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00)));
|
||||
expect(bufferDecoder.subBufferDecoder(1, 0))
|
||||
.toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer()));
|
||||
expect(bufferDecoder.subBufferDecoder(1, 1))
|
||||
.toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01)));
|
||||
expect(bufferDecoder.subBufferDecoder(1, 2))
|
||||
.toEqual(BufferDecoder.fromArrayBuffer(createArrayBuffer(0x01, 0x02)));
|
||||
});
|
||||
|
||||
it('can not create invalid', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x00, 0x01, 0x02));
|
||||
if (CHECK_STATE) {
|
||||
expect(() => bufferDecoder.subBufferDecoder(-1, 1)).toThrow();
|
||||
expect(() => bufferDecoder.subBufferDecoder(0, -4)).toThrow();
|
||||
expect(() => bufferDecoder.subBufferDecoder(0, 4)).toThrow();
|
||||
}
|
||||
});
|
||||
});
|
91
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_request.js
vendored
Normal file
91
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_request.js
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @fileoverview Handwritten code of ConformanceRequest.
|
||||
*/
|
||||
goog.module('proto.conformance.ConformanceRequest');
|
||||
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
const WireFormat = goog.require('proto.conformance.WireFormat');
|
||||
|
||||
/**
|
||||
* Handwritten code of conformance.ConformanceRequest.
|
||||
* This is used to send request from the conformance test runner to the testee.
|
||||
* Check //third_party/protobuf/testing/protobuf/conformance/conformance.proto
|
||||
* for more details.
|
||||
* @final
|
||||
*/
|
||||
class ConformanceRequest {
|
||||
/**
|
||||
* @param {!ArrayBuffer} bytes
|
||||
* @private
|
||||
*/
|
||||
constructor(bytes) {
|
||||
/** @private @const {!Kernel} */
|
||||
this.accessor_ = Kernel.fromArrayBuffer(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a request instance with the given bytes data.
|
||||
* @param {!ArrayBuffer} bytes
|
||||
* @return {!ConformanceRequest}
|
||||
*/
|
||||
static deserialize(bytes) {
|
||||
return new ConformanceRequest(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the protobuf_payload.
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
getProtobufPayload() {
|
||||
return this.accessor_.getBytesWithDefault(1).toArrayBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the requested_output_format.
|
||||
* @return {!WireFormat}
|
||||
*/
|
||||
getRequestedOutputFormat() {
|
||||
return /** @type {!WireFormat} */ (this.accessor_.getInt32WithDefault(3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message_type.
|
||||
* @return {string}
|
||||
*/
|
||||
getMessageType() {
|
||||
return this.accessor_.getStringWithDefault(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the oneof case for payload field.
|
||||
* This implementation assumes only one field in a oneof group is set.
|
||||
* @return {!ConformanceRequest.PayloadCase}
|
||||
*/
|
||||
getPayloadCase() {
|
||||
if (this.accessor_.hasFieldNumber(1)) {
|
||||
return /** @type {!ConformanceRequest.PayloadCase} */ (
|
||||
ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD);
|
||||
} else if (this.accessor_.hasFieldNumber(2)) {
|
||||
return /** @type {!ConformanceRequest.PayloadCase} */ (
|
||||
ConformanceRequest.PayloadCase.JSON_PAYLOAD);
|
||||
} else if (this.accessor_.hasFieldNumber(8)) {
|
||||
return /** @type {!ConformanceRequest.PayloadCase} */ (
|
||||
ConformanceRequest.PayloadCase.TEXT_PAYLOAD);
|
||||
} else {
|
||||
return /** @type {!ConformanceRequest.PayloadCase} */ (
|
||||
ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
ConformanceRequest.PayloadCase = {
|
||||
PAYLOAD_NOT_SET: 0,
|
||||
PROTOBUF_PAYLOAD: 1,
|
||||
JSON_PAYLOAD: 2,
|
||||
TEXT_PAYLOAD: 8,
|
||||
};
|
||||
|
||||
exports = ConformanceRequest;
|
76
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_response.js
vendored
Normal file
76
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_response.js
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @fileoverview Handwritten code of ConformanceResponse.
|
||||
*/
|
||||
goog.module('proto.conformance.ConformanceResponse');
|
||||
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
|
||||
/**
|
||||
* Handwritten code of conformance.ConformanceResponse.
|
||||
* This is used to send response from the conformance testee to the test runner.
|
||||
* Check //third_party/protobuf/testing/protobuf/conformance/conformance.proto
|
||||
* for more details.
|
||||
* @final
|
||||
*/
|
||||
class ConformanceResponse {
|
||||
/**
|
||||
* @param {!ArrayBuffer} bytes
|
||||
* @private
|
||||
*/
|
||||
constructor(bytes) {
|
||||
/** @private @const {!Kernel} */
|
||||
this.accessor_ = Kernel.fromArrayBuffer(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty response instance.
|
||||
* @return {!ConformanceResponse}
|
||||
*/
|
||||
static createEmpty() {
|
||||
return new ConformanceResponse(new ArrayBuffer(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets parse_error field.
|
||||
* @param {string} value
|
||||
*/
|
||||
setParseError(value) {
|
||||
this.accessor_.setString(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets runtime_error field.
|
||||
* @param {string} value
|
||||
*/
|
||||
setRuntimeError(value) {
|
||||
this.accessor_.setString(2, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets protobuf_payload field.
|
||||
* @param {!ArrayBuffer} value
|
||||
*/
|
||||
setProtobufPayload(value) {
|
||||
const bytesString = ByteString.fromArrayBuffer(value);
|
||||
this.accessor_.setBytes(3, bytesString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets skipped field.
|
||||
* @param {string} value
|
||||
*/
|
||||
setSkipped(value) {
|
||||
this.accessor_.setString(5, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes into binary data.
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
serialize() {
|
||||
return this.accessor_.serialize();
|
||||
}
|
||||
}
|
||||
|
||||
exports = ConformanceResponse;
|
103
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_testee.js
vendored
Normal file
103
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_testee.js
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
goog.module('javascript.protobuf.conformance');
|
||||
|
||||
const ConformanceRequest = goog.require('proto.conformance.ConformanceRequest');
|
||||
const ConformanceResponse = goog.require('proto.conformance.ConformanceResponse');
|
||||
const TestAllTypesProto2 = goog.require('proto.conformance.TestAllTypesProto2');
|
||||
const TestAllTypesProto3 = goog.require('proto.conformance.TestAllTypesProto3');
|
||||
const WireFormat = goog.require('proto.conformance.WireFormat');
|
||||
const base64 = goog.require('goog.crypt.base64');
|
||||
|
||||
/**
|
||||
* Creates a `proto.conformance.ConformanceResponse` response according to the
|
||||
* `proto.conformance.ConformanceRequest` request.
|
||||
* @param {!ConformanceRequest} request
|
||||
* @return {!ConformanceResponse} response
|
||||
*/
|
||||
function doTest(request) {
|
||||
const response = ConformanceResponse.createEmpty();
|
||||
|
||||
if(request.getPayloadCase() === ConformanceRequest.PayloadCase.JSON_PAYLOAD) {
|
||||
response.setSkipped('Json is not supported as input format.');
|
||||
return response;
|
||||
}
|
||||
|
||||
if(request.getPayloadCase() === ConformanceRequest.PayloadCase.TEXT_PAYLOAD) {
|
||||
response.setSkipped('Text format is not supported as input format.');
|
||||
return response;
|
||||
}
|
||||
|
||||
if(request.getPayloadCase() === ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET) {
|
||||
response.setRuntimeError('Request didn\'t have payload.');
|
||||
return response;
|
||||
}
|
||||
|
||||
if(request.getPayloadCase() !== ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD) {
|
||||
throw new Error('Request didn\'t have accepted input format.');
|
||||
}
|
||||
|
||||
if (request.getRequestedOutputFormat() === WireFormat.JSON) {
|
||||
response.setSkipped('Json is not supported as output format.');
|
||||
return response;
|
||||
}
|
||||
|
||||
if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) {
|
||||
response.setSkipped('Text format is not supported as output format.');
|
||||
return response;
|
||||
}
|
||||
|
||||
if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) {
|
||||
response.setRuntimeError('Unspecified output format');
|
||||
return response;
|
||||
}
|
||||
|
||||
if (request.getRequestedOutputFormat() !== WireFormat.PROTOBUF) {
|
||||
throw new Error('Request didn\'t have accepted output format.');
|
||||
}
|
||||
|
||||
if (request.getMessageType() === 'conformance.FailureSet') {
|
||||
response.setProtobufPayload(new ArrayBuffer(0));
|
||||
} else if (
|
||||
request.getMessageType() ===
|
||||
'protobuf_test_messages.proto2.TestAllTypesProto2') {
|
||||
try {
|
||||
const testMessage =
|
||||
TestAllTypesProto2.deserialize(request.getProtobufPayload());
|
||||
response.setProtobufPayload(testMessage.serialize());
|
||||
} catch (err) {
|
||||
response.setParseError(err.toString());
|
||||
}
|
||||
} else if (
|
||||
request.getMessageType() ===
|
||||
'protobuf_test_messages.proto3.TestAllTypesProto3') {
|
||||
try {
|
||||
const testMessage =
|
||||
TestAllTypesProto3.deserialize(request.getProtobufPayload());
|
||||
response.setProtobufPayload(testMessage.serialize());
|
||||
} catch (err) {
|
||||
response.setParseError(err.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`Payload message not supported: ${request.getMessageType()}.`);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as doTest, but both request and response are in base64.
|
||||
* @param {string} base64Request
|
||||
* @return {string} response
|
||||
*/
|
||||
function runConformanceTest(base64Request) {
|
||||
const request =
|
||||
ConformanceRequest.deserialize(
|
||||
base64.decodeStringToUint8Array(base64Request).buffer);
|
||||
const response = doTest(request);
|
||||
return base64.encodeByteArray(new Uint8Array(response.serialize()));
|
||||
}
|
||||
|
||||
// Needed for node test
|
||||
exports.doTest = doTest;
|
||||
// Needed for browser test
|
||||
goog.exportSymbol('runConformanceTest', runConformanceTest);
|
62
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js
vendored
Normal file
62
deps/protobuf/js/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
const ConformanceRequest = goog.require('proto.conformance.ConformanceRequest');
|
||||
const {doTest} = goog.require('javascript.protobuf.conformance');
|
||||
const fs = require('fs');
|
||||
|
||||
|
||||
/**
|
||||
* Reads a buffer of N bytes.
|
||||
* @param {number} bytes Number of bytes to read.
|
||||
* @return {!Buffer} Buffer which contains data.
|
||||
*/
|
||||
function readBuffer(bytes) {
|
||||
// Linux cannot use process.stdin.fd (which isn't set up as sync)
|
||||
const buf = new Buffer.alloc(bytes);
|
||||
const fd = fs.openSync('/dev/stdin', 'r');
|
||||
fs.readSync(fd, buf, 0, bytes);
|
||||
fs.closeSync(fd);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all data in buffer.
|
||||
* @param {!Buffer} buffer Buffer which contains data.
|
||||
*/
|
||||
function writeBuffer(buffer) {
|
||||
// Under linux, process.stdout.fd is async. Needs to open stdout in a synced
|
||||
// way for sync write.
|
||||
const fd = fs.openSync('/dev/stdout', 'w');
|
||||
fs.writeSync(fd, buffer, 0, buffer.length);
|
||||
fs.closeSync(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the test ran successfully, false on legitimate EOF.
|
||||
* @return {boolean} Whether to continue test.
|
||||
*/
|
||||
function runConformanceTest() {
|
||||
const requestLengthBuf = readBuffer(4);
|
||||
const requestLength = requestLengthBuf.readInt32LE(0);
|
||||
if (!requestLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const serializedRequest = readBuffer(requestLength);
|
||||
const array = new Uint8Array(serializedRequest);
|
||||
const request = ConformanceRequest.deserialize(array.buffer);
|
||||
const response = doTest(request);
|
||||
|
||||
const serializedResponse = response.serialize();
|
||||
|
||||
const responseLengthBuf = new Buffer.alloc(4);
|
||||
responseLengthBuf.writeInt32LE(serializedResponse.byteLength, 0);
|
||||
writeBuffer(responseLengthBuf);
|
||||
writeBuffer(new Buffer.from(serializedResponse));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (!runConformanceTest()) {
|
||||
break;
|
||||
}
|
||||
}
|
309
deps/protobuf/js/experimental/runtime/kernel/conformance/test_all_types_proto2.js
vendored
Normal file
309
deps/protobuf/js/experimental/runtime/kernel/conformance/test_all_types_proto2.js
vendored
Normal file
@ -0,0 +1,309 @@
|
||||
/**
|
||||
* @fileoverview Handwritten code of TestAllTypesProto2.
|
||||
*/
|
||||
goog.module('proto.conformance.TestAllTypesProto2');
|
||||
|
||||
const InternalMessage = goog.require('protobuf.binary.InternalMessage');
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
|
||||
/**
|
||||
* Handwritten code of conformance.TestAllTypesProto2.
|
||||
* Check google/protobuf/test_messages_proto3.proto for more details.
|
||||
* @implements {InternalMessage}
|
||||
* @final
|
||||
*/
|
||||
class TestAllTypesProto2 {
|
||||
/**
|
||||
* @param {!Kernel=} accessor
|
||||
* @private
|
||||
*/
|
||||
constructor(accessor = Kernel.createEmpty()) {
|
||||
/** @private @const {!Kernel} */
|
||||
this.accessor_ = accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @package
|
||||
* @return {!Kernel}
|
||||
*/
|
||||
internalGetKernel() {
|
||||
return this.accessor_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a request instance with the given bytes data.
|
||||
* If we directly use the accessor created by the binary decoding, the
|
||||
* Kernel instance will only copy the same data over for encoding. By
|
||||
* explicitly fetching data from the previous accessor and setting all fields
|
||||
* into a new accessor, we will actually test encoding/decoding for the binary
|
||||
* format.
|
||||
* @param {!ArrayBuffer} bytes
|
||||
* @return {!TestAllTypesProto2}
|
||||
*/
|
||||
static deserialize(bytes) {
|
||||
const msg = new TestAllTypesProto2();
|
||||
const requestAccessor = Kernel.fromArrayBuffer(bytes);
|
||||
|
||||
if (requestAccessor.hasFieldNumber(1)) {
|
||||
const value = requestAccessor.getInt32WithDefault(1);
|
||||
msg.accessor_.setInt32(1, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(2)) {
|
||||
const value = requestAccessor.getInt64WithDefault(2);
|
||||
msg.accessor_.setInt64(2, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(3)) {
|
||||
const value = requestAccessor.getUint32WithDefault(3);
|
||||
msg.accessor_.setUint32(3, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(4)) {
|
||||
const value = requestAccessor.getUint64WithDefault(4);
|
||||
msg.accessor_.setUint64(4, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(5)) {
|
||||
const value = requestAccessor.getSint32WithDefault(5);
|
||||
msg.accessor_.setSint32(5, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(6)) {
|
||||
const value = requestAccessor.getSint64WithDefault(6);
|
||||
msg.accessor_.setSint64(6, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(7)) {
|
||||
const value = requestAccessor.getFixed32WithDefault(7);
|
||||
msg.accessor_.setFixed32(7, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(8)) {
|
||||
const value = requestAccessor.getFixed64WithDefault(8);
|
||||
msg.accessor_.setFixed64(8, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(9)) {
|
||||
const value = requestAccessor.getSfixed32WithDefault(9);
|
||||
msg.accessor_.setSfixed32(9, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(10)) {
|
||||
const value = requestAccessor.getSfixed64WithDefault(10);
|
||||
msg.accessor_.setSfixed64(10, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(11)) {
|
||||
const value = requestAccessor.getFloatWithDefault(11);
|
||||
msg.accessor_.setFloat(11, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(12)) {
|
||||
const value = requestAccessor.getDoubleWithDefault(12);
|
||||
msg.accessor_.setDouble(12, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(13)) {
|
||||
const value = requestAccessor.getBoolWithDefault(13);
|
||||
msg.accessor_.setBool(13, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(14)) {
|
||||
const value = requestAccessor.getStringWithDefault(14);
|
||||
msg.accessor_.setString(14, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(15)) {
|
||||
const value = requestAccessor.getBytesWithDefault(15);
|
||||
msg.accessor_.setBytes(15, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(18)) {
|
||||
const value = requestAccessor.getMessage(
|
||||
18, (accessor) => new TestAllTypesProto2(accessor));
|
||||
msg.accessor_.setMessage(18, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(21)) {
|
||||
// Unknown enum is not checked here, because even if an enum is unknown,
|
||||
// it should be kept during encoding. For the purpose of wire format test,
|
||||
// we can simplify the implementation by treating it as an int32 field,
|
||||
// which has the same semantic except for the unknown value checking.
|
||||
const value = requestAccessor.getInt32WithDefault(21);
|
||||
msg.accessor_.setInt32(21, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(31)) {
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(31);
|
||||
msg.accessor_.setUnpackedInt32Iterable(31, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(32)) {
|
||||
const value = requestAccessor.getRepeatedInt64Iterable(32);
|
||||
msg.accessor_.setUnpackedInt64Iterable(32, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(33)) {
|
||||
const value = requestAccessor.getRepeatedUint32Iterable(33);
|
||||
msg.accessor_.setUnpackedUint32Iterable(33, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(34)) {
|
||||
const value = requestAccessor.getRepeatedUint64Iterable(34);
|
||||
msg.accessor_.setUnpackedUint64Iterable(34, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(35)) {
|
||||
const value = requestAccessor.getRepeatedSint32Iterable(35);
|
||||
msg.accessor_.setUnpackedSint32Iterable(35, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(36)) {
|
||||
const value = requestAccessor.getRepeatedSint64Iterable(36);
|
||||
msg.accessor_.setUnpackedSint64Iterable(36, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(37)) {
|
||||
const value = requestAccessor.getRepeatedFixed32Iterable(37);
|
||||
msg.accessor_.setUnpackedFixed32Iterable(37, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(38)) {
|
||||
const value = requestAccessor.getRepeatedFixed64Iterable(38);
|
||||
msg.accessor_.setUnpackedFixed64Iterable(38, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(39)) {
|
||||
const value = requestAccessor.getRepeatedSfixed32Iterable(39);
|
||||
msg.accessor_.setUnpackedSfixed32Iterable(39, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(40)) {
|
||||
const value = requestAccessor.getRepeatedSfixed64Iterable(40);
|
||||
msg.accessor_.setUnpackedSfixed64Iterable(40, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(41)) {
|
||||
const value = requestAccessor.getRepeatedFloatIterable(41);
|
||||
msg.accessor_.setUnpackedFloatIterable(41, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(42)) {
|
||||
const value = requestAccessor.getRepeatedDoubleIterable(42);
|
||||
msg.accessor_.setUnpackedDoubleIterable(42, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(43)) {
|
||||
const value = requestAccessor.getRepeatedBoolIterable(43);
|
||||
msg.accessor_.setUnpackedBoolIterable(43, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(44)) {
|
||||
const value = requestAccessor.getRepeatedStringIterable(44);
|
||||
msg.accessor_.setRepeatedStringIterable(44, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(45)) {
|
||||
const value = requestAccessor.getRepeatedBytesIterable(45);
|
||||
msg.accessor_.setRepeatedBytesIterable(45, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(48)) {
|
||||
const value = requestAccessor.getRepeatedMessageIterable(
|
||||
48, (accessor) => new TestAllTypesProto2(accessor));
|
||||
msg.accessor_.setRepeatedMessageIterable(48, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(51)) {
|
||||
// Unknown enum is not checked here, because even if an enum is unknown,
|
||||
// it should be kept during encoding. For the purpose of wire format test,
|
||||
// we can simplify the implementation by treating it as an int32 field,
|
||||
// which has the same semantic except for the unknown value checking.
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(51);
|
||||
msg.accessor_.setUnpackedInt32Iterable(51, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(75)) {
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(75);
|
||||
msg.accessor_.setPackedInt32Iterable(75, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(76)) {
|
||||
const value = requestAccessor.getRepeatedInt64Iterable(76);
|
||||
msg.accessor_.setPackedInt64Iterable(76, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(77)) {
|
||||
const value = requestAccessor.getRepeatedUint32Iterable(77);
|
||||
msg.accessor_.setPackedUint32Iterable(77, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(78)) {
|
||||
const value = requestAccessor.getRepeatedUint64Iterable(78);
|
||||
msg.accessor_.setPackedUint64Iterable(78, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(79)) {
|
||||
const value = requestAccessor.getRepeatedSint32Iterable(79);
|
||||
msg.accessor_.setPackedSint32Iterable(79, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(80)) {
|
||||
const value = requestAccessor.getRepeatedSint64Iterable(80);
|
||||
msg.accessor_.setPackedSint64Iterable(80, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(81)) {
|
||||
const value = requestAccessor.getRepeatedFixed32Iterable(81);
|
||||
msg.accessor_.setPackedFixed32Iterable(81, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(82)) {
|
||||
const value = requestAccessor.getRepeatedFixed64Iterable(82);
|
||||
msg.accessor_.setPackedFixed64Iterable(82, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(83)) {
|
||||
const value = requestAccessor.getRepeatedSfixed32Iterable(83);
|
||||
msg.accessor_.setPackedSfixed32Iterable(83, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(84)) {
|
||||
const value = requestAccessor.getRepeatedSfixed64Iterable(84);
|
||||
msg.accessor_.setPackedSfixed64Iterable(84, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(85)) {
|
||||
const value = requestAccessor.getRepeatedFloatIterable(85);
|
||||
msg.accessor_.setPackedFloatIterable(85, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(86)) {
|
||||
const value = requestAccessor.getRepeatedDoubleIterable(86);
|
||||
msg.accessor_.setPackedDoubleIterable(86, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(87)) {
|
||||
const value = requestAccessor.getRepeatedBoolIterable(87);
|
||||
msg.accessor_.setPackedBoolIterable(87, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(88)) {
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(88);
|
||||
msg.accessor_.setPackedInt32Iterable(88, value);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes into binary data.
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
serialize() {
|
||||
return this.accessor_.serialize();
|
||||
}
|
||||
}
|
||||
|
||||
exports = TestAllTypesProto2;
|
310
deps/protobuf/js/experimental/runtime/kernel/conformance/test_all_types_proto3.js
vendored
Normal file
310
deps/protobuf/js/experimental/runtime/kernel/conformance/test_all_types_proto3.js
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
/**
|
||||
* @fileoverview Handwritten code of TestAllTypesProto3.
|
||||
*/
|
||||
goog.module('proto.conformance.TestAllTypesProto3');
|
||||
|
||||
const InternalMessage = goog.require('protobuf.binary.InternalMessage');
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
|
||||
/**
|
||||
* Handwritten code of conformance.TestAllTypesProto3.
|
||||
* Check google/protobuf/test_messages_proto3.proto for more details.
|
||||
* @implements {InternalMessage}
|
||||
* @final
|
||||
*/
|
||||
class TestAllTypesProto3 {
|
||||
/**
|
||||
* @param {!Kernel=} accessor
|
||||
* @private
|
||||
*/
|
||||
constructor(accessor = Kernel.createEmpty()) {
|
||||
/** @private @const {!Kernel} */
|
||||
this.accessor_ = accessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @package
|
||||
* @return {!Kernel}
|
||||
*/
|
||||
internalGetKernel() {
|
||||
return this.accessor_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a request instance with the given bytes data.
|
||||
* If we directly use the accessor created by the binary decoding, the
|
||||
* Kernel instance will only copy the same data over for encoding. By
|
||||
* explicitly fetching data from the previous accessor and setting all fields
|
||||
* into a new accessor, we will actually test encoding/decoding for the binary
|
||||
* format.
|
||||
* @param {!ArrayBuffer} bytes
|
||||
* @return {!TestAllTypesProto3}
|
||||
*/
|
||||
static deserialize(bytes) {
|
||||
const msg = new TestAllTypesProto3();
|
||||
const requestAccessor = Kernel.fromArrayBuffer(bytes);
|
||||
|
||||
if (requestAccessor.hasFieldNumber(1)) {
|
||||
const value = requestAccessor.getInt32WithDefault(1);
|
||||
msg.accessor_.setInt32(1, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(2)) {
|
||||
const value = requestAccessor.getInt64WithDefault(2);
|
||||
msg.accessor_.setInt64(2, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(3)) {
|
||||
const value = requestAccessor.getUint32WithDefault(3);
|
||||
msg.accessor_.setUint32(3, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(4)) {
|
||||
const value = requestAccessor.getUint64WithDefault(4);
|
||||
msg.accessor_.setUint64(4, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(5)) {
|
||||
const value = requestAccessor.getSint32WithDefault(5);
|
||||
msg.accessor_.setSint32(5, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(6)) {
|
||||
const value = requestAccessor.getSint64WithDefault(6);
|
||||
msg.accessor_.setSint64(6, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(7)) {
|
||||
const value = requestAccessor.getFixed32WithDefault(7);
|
||||
msg.accessor_.setFixed32(7, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(8)) {
|
||||
const value = requestAccessor.getFixed64WithDefault(8);
|
||||
msg.accessor_.setFixed64(8, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(9)) {
|
||||
const value = requestAccessor.getSfixed32WithDefault(9);
|
||||
msg.accessor_.setSfixed32(9, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(10)) {
|
||||
const value = requestAccessor.getSfixed64WithDefault(10);
|
||||
msg.accessor_.setSfixed64(10, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(11)) {
|
||||
const value = requestAccessor.getFloatWithDefault(11);
|
||||
msg.accessor_.setFloat(11, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(12)) {
|
||||
const value = requestAccessor.getDoubleWithDefault(12);
|
||||
msg.accessor_.setDouble(12, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(13)) {
|
||||
const value = requestAccessor.getBoolWithDefault(13);
|
||||
msg.accessor_.setBool(13, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(14)) {
|
||||
const value = requestAccessor.getStringWithDefault(14);
|
||||
msg.accessor_.setString(14, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(15)) {
|
||||
const value = requestAccessor.getBytesWithDefault(15);
|
||||
msg.accessor_.setBytes(15, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(18)) {
|
||||
const value = requestAccessor.getMessage(
|
||||
18, (accessor) => new TestAllTypesProto3(accessor));
|
||||
msg.accessor_.setMessage(18, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(21)) {
|
||||
// Unknown enum is not checked here, because even if an enum is unknown,
|
||||
// it should be kept during encoding. For the purpose of wire format test,
|
||||
// we can simplify the implementation by treating it as an int32 field,
|
||||
// which has the same semantic except for the unknown value checking.
|
||||
const value = requestAccessor.getInt32WithDefault(21);
|
||||
msg.accessor_.setInt32(21, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(31)) {
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(31);
|
||||
msg.accessor_.setPackedInt32Iterable(31, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(32)) {
|
||||
const value = requestAccessor.getRepeatedInt64Iterable(32);
|
||||
msg.accessor_.setPackedInt64Iterable(32, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(33)) {
|
||||
const value = requestAccessor.getRepeatedUint32Iterable(33);
|
||||
msg.accessor_.setPackedUint32Iterable(33, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(34)) {
|
||||
const value = requestAccessor.getRepeatedUint64Iterable(34);
|
||||
msg.accessor_.setPackedUint64Iterable(34, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(35)) {
|
||||
const value = requestAccessor.getRepeatedSint32Iterable(35);
|
||||
msg.accessor_.setPackedSint32Iterable(35, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(36)) {
|
||||
const value = requestAccessor.getRepeatedSint64Iterable(36);
|
||||
msg.accessor_.setPackedSint64Iterable(36, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(37)) {
|
||||
const value = requestAccessor.getRepeatedFixed32Iterable(37);
|
||||
msg.accessor_.setPackedFixed32Iterable(37, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(38)) {
|
||||
const value = requestAccessor.getRepeatedFixed64Iterable(38);
|
||||
msg.accessor_.setPackedFixed64Iterable(38, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(39)) {
|
||||
const value = requestAccessor.getRepeatedSfixed32Iterable(39);
|
||||
msg.accessor_.setPackedSfixed32Iterable(39, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(40)) {
|
||||
const value = requestAccessor.getRepeatedSfixed64Iterable(40);
|
||||
msg.accessor_.setPackedSfixed64Iterable(40, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(41)) {
|
||||
const value = requestAccessor.getRepeatedFloatIterable(41);
|
||||
msg.accessor_.setPackedFloatIterable(41, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(42)) {
|
||||
const value = requestAccessor.getRepeatedDoubleIterable(42);
|
||||
msg.accessor_.setPackedDoubleIterable(42, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(43)) {
|
||||
const value = requestAccessor.getRepeatedBoolIterable(43);
|
||||
msg.accessor_.setPackedBoolIterable(43, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(44)) {
|
||||
const value = requestAccessor.getRepeatedStringIterable(44);
|
||||
msg.accessor_.setRepeatedStringIterable(44, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(45)) {
|
||||
const value = requestAccessor.getRepeatedBytesIterable(45);
|
||||
msg.accessor_.setRepeatedBytesIterable(45, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(48)) {
|
||||
const value = requestAccessor.getRepeatedMessageIterable(
|
||||
48, (accessor) => new TestAllTypesProto3(accessor));
|
||||
msg.accessor_.setRepeatedMessageIterable(48, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(51)) {
|
||||
// Unknown enum is not checked here, because even if an enum is unknown,
|
||||
// it should be kept during encoding. For the purpose of wire format test,
|
||||
// we can simplify the implementation by treating it as an int32 field,
|
||||
// which has the same semantic except for the unknown value checking.
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(51);
|
||||
msg.accessor_.setPackedInt32Iterable(51, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(89)) {
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(89);
|
||||
msg.accessor_.setUnpackedInt32Iterable(89, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(90)) {
|
||||
const value = requestAccessor.getRepeatedInt64Iterable(90);
|
||||
msg.accessor_.setUnpackedInt64Iterable(90, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(91)) {
|
||||
const value = requestAccessor.getRepeatedUint32Iterable(91);
|
||||
msg.accessor_.setUnpackedUint32Iterable(91, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(92)) {
|
||||
const value = requestAccessor.getRepeatedUint64Iterable(92);
|
||||
msg.accessor_.setUnpackedUint64Iterable(92, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(93)) {
|
||||
const value = requestAccessor.getRepeatedSint32Iterable(93);
|
||||
msg.accessor_.setUnpackedSint32Iterable(93, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(94)) {
|
||||
const value = requestAccessor.getRepeatedSint64Iterable(94);
|
||||
msg.accessor_.setUnpackedSint64Iterable(94, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(95)) {
|
||||
const value = requestAccessor.getRepeatedFixed32Iterable(95);
|
||||
msg.accessor_.setUnpackedFixed32Iterable(95, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(96)) {
|
||||
const value = requestAccessor.getRepeatedFixed64Iterable(96);
|
||||
msg.accessor_.setUnpackedFixed64Iterable(96, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(97)) {
|
||||
const value = requestAccessor.getRepeatedSfixed32Iterable(97);
|
||||
msg.accessor_.setUnpackedSfixed32Iterable(97, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(98)) {
|
||||
const value = requestAccessor.getRepeatedSfixed64Iterable(98);
|
||||
msg.accessor_.setUnpackedSfixed64Iterable(98, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(99)) {
|
||||
const value = requestAccessor.getRepeatedFloatIterable(99);
|
||||
msg.accessor_.setUnpackedFloatIterable(99, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(100)) {
|
||||
const value = requestAccessor.getRepeatedDoubleIterable(100);
|
||||
msg.accessor_.setUnpackedDoubleIterable(100, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(101)) {
|
||||
const value = requestAccessor.getRepeatedBoolIterable(101);
|
||||
msg.accessor_.setUnpackedBoolIterable(101, value);
|
||||
}
|
||||
|
||||
if (requestAccessor.hasFieldNumber(102)) {
|
||||
const value = requestAccessor.getRepeatedInt32Iterable(102);
|
||||
msg.accessor_.setUnpackedInt32Iterable(102, value);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes into binary data.
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
serialize() {
|
||||
return this.accessor_.serialize();
|
||||
}
|
||||
}
|
||||
|
||||
exports = TestAllTypesProto3;
|
16
deps/protobuf/js/experimental/runtime/kernel/conformance/wire_format.js
vendored
Normal file
16
deps/protobuf/js/experimental/runtime/kernel/conformance/wire_format.js
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @fileoverview Handwritten code of WireFormat.
|
||||
*/
|
||||
goog.module('proto.conformance.WireFormat');
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
const WireFormat = {
|
||||
UNSPECIFIED: 0,
|
||||
PROTOBUF: 1,
|
||||
JSON: 2,
|
||||
TEXT_FORMAT: 4,
|
||||
};
|
||||
|
||||
exports = WireFormat;
|
89
deps/protobuf/js/experimental/runtime/kernel/double_test_pairs.js
vendored
Normal file
89
deps/protobuf/js/experimental/runtime/kernel/double_test_pairs.js
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @fileoverview Test data for double encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.doubleTestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of double values and their bit representation.
|
||||
* This is used to test encoding and decoding from the protobuf wire format.
|
||||
* @return {!Array<{name: string, doubleValue:number, bufferDecoder:
|
||||
* !BufferDecoder}>}
|
||||
*/
|
||||
function getDoublePairs() {
|
||||
const doublePairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
doubleValue: 0,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
},
|
||||
{
|
||||
name: 'minus zero',
|
||||
doubleValue: -0,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80)
|
||||
},
|
||||
{
|
||||
name: 'one',
|
||||
doubleValue: 1,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F)
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
doubleValue: -1,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xBF)
|
||||
},
|
||||
|
||||
{
|
||||
name: 'PI',
|
||||
doubleValue: Math.PI,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40)
|
||||
|
||||
},
|
||||
{
|
||||
name: 'max value',
|
||||
doubleValue: Number.MAX_VALUE,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F)
|
||||
},
|
||||
{
|
||||
name: 'min value',
|
||||
doubleValue: Number.MIN_VALUE,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
},
|
||||
{
|
||||
name: 'Infinity',
|
||||
doubleValue: Infinity,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7F)
|
||||
},
|
||||
{
|
||||
name: 'minus Infinity',
|
||||
doubleValue: -Infinity,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF)
|
||||
},
|
||||
{
|
||||
name: 'Number.MAX_SAFE_INTEGER',
|
||||
doubleValue: Number.MAX_SAFE_INTEGER,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x43)
|
||||
},
|
||||
{
|
||||
name: 'Number.MIN_SAFE_INTEGER',
|
||||
doubleValue: Number.MIN_SAFE_INTEGER,
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xC3)
|
||||
},
|
||||
];
|
||||
return [...doublePairs];
|
||||
}
|
||||
|
||||
exports = {getDoublePairs};
|
196
deps/protobuf/js/experimental/runtime/kernel/field.js
vendored
Normal file
196
deps/protobuf/js/experimental/runtime/kernel/field.js
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
/**
|
||||
* @fileoverview Contains classes that hold data for a protobuf field.
|
||||
*/
|
||||
|
||||
goog.module('protobuf.binary.field');
|
||||
|
||||
const WireType = goog.requireType('protobuf.binary.WireType');
|
||||
const Writer = goog.requireType('protobuf.binary.Writer');
|
||||
const {checkDefAndNotNull, checkState} = goog.require('protobuf.internal.checks');
|
||||
|
||||
/**
|
||||
* Number of bits taken to represent a wire type.
|
||||
* @const {number}
|
||||
*/
|
||||
const WIRE_TYPE_LENGTH_BITS = 3;
|
||||
|
||||
/** @const {number} */
|
||||
const WIRE_TYPE_EXTRACTOR = (1 << WIRE_TYPE_LENGTH_BITS) - 1;
|
||||
|
||||
/**
|
||||
* An IndexEntry consists of the wire type and the position of a field in the
|
||||
* binary data. The wire type and the position are encoded into a single number
|
||||
* to save memory, which can be decoded using Field.getWireType() and
|
||||
* Field.getStartIndex() methods.
|
||||
* @typedef {number}
|
||||
*/
|
||||
let IndexEntry;
|
||||
|
||||
/**
|
||||
* An entry containing the index into the binary data and/or the corresponding
|
||||
* cached JS object(s) for a field.
|
||||
* @template T
|
||||
* @final
|
||||
* @package
|
||||
*/
|
||||
class Field {
|
||||
/**
|
||||
* Creates a field and inserts the wireType and position of the first
|
||||
* occurrence of a field.
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} startIndex
|
||||
* @return {!Field}
|
||||
*/
|
||||
static fromFirstIndexEntry(wireType, startIndex) {
|
||||
return new Field([Field.encodeIndexEntry(wireType, startIndex)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {T} decodedValue The cached JS object decoded from the binary data.
|
||||
* @param {function(!Writer, number, T):void|undefined} encoder Write function
|
||||
* to encode the cache into binary bytes.
|
||||
* @return {!Field}
|
||||
* @template T
|
||||
*/
|
||||
static fromDecodedValue(decodedValue, encoder) {
|
||||
return new Field(null, decodedValue, encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} startIndex
|
||||
* @return {!IndexEntry}
|
||||
*/
|
||||
static encodeIndexEntry(wireType, startIndex) {
|
||||
return startIndex << WIRE_TYPE_LENGTH_BITS | wireType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!IndexEntry} indexEntry
|
||||
* @return {!WireType}
|
||||
*/
|
||||
static getWireType(indexEntry) {
|
||||
return /** @type {!WireType} */ (indexEntry & WIRE_TYPE_EXTRACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!IndexEntry} indexEntry
|
||||
* @return {number}
|
||||
*/
|
||||
static getStartIndex(indexEntry) {
|
||||
return indexEntry >> WIRE_TYPE_LENGTH_BITS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Array<!IndexEntry>} indexArray
|
||||
* @param {T=} decodedValue
|
||||
* @param {function(!Writer, number, T):void=} encoder
|
||||
* @private
|
||||
*/
|
||||
constructor(indexArray, decodedValue = undefined, encoder = undefined) {
|
||||
checkState(
|
||||
!!indexArray || decodedValue !== undefined,
|
||||
'At least one of indexArray and decodedValue must be set');
|
||||
|
||||
/** @private {?Array<!IndexEntry>} */
|
||||
this.indexArray_ = indexArray;
|
||||
/** @private {T|undefined} */
|
||||
this.decodedValue_ = decodedValue;
|
||||
// TODO: Consider storing an enum to represent encoder
|
||||
/** @private {function(!Writer, number, T)|undefined} */
|
||||
this.encoder_ = encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new IndexEntry.
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} startIndex
|
||||
*/
|
||||
addIndexEntry(wireType, startIndex) {
|
||||
checkDefAndNotNull(this.indexArray_)
|
||||
.push(Field.encodeIndexEntry(wireType, startIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of IndexEntry.
|
||||
* @return {?Array<!IndexEntry>}
|
||||
*/
|
||||
getIndexArray() {
|
||||
return this.indexArray_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the decoded value and sets the write function to encode cache into
|
||||
* binary bytes.
|
||||
* @param {T} decodedValue
|
||||
* @param {function(!Writer, number, T):void|undefined} encoder
|
||||
*/
|
||||
setCache(decodedValue, encoder) {
|
||||
this.decodedValue_ = decodedValue;
|
||||
this.encoder_ = encoder;
|
||||
this.maybeRemoveIndexArray_();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the decoded value has been set.
|
||||
* @return {boolean}
|
||||
*/
|
||||
hasDecodedValue() {
|
||||
return this.decodedValue_ !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached decoded value. The value needs to be set when this
|
||||
* method is called.
|
||||
* @return {T}
|
||||
*/
|
||||
getDecodedValue() {
|
||||
// Makes sure that the decoded value in the cache has already been set. This
|
||||
// prevents callers from doing `if (field.getDecodedValue()) {...}` to check
|
||||
// if a value exist in the cache, because the check might return false even
|
||||
// if the cache has a valid value set (e.g. 0 or empty string).
|
||||
checkState(this.decodedValue_ !== undefined);
|
||||
return this.decodedValue_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the write function to encode cache into binary bytes.
|
||||
* @return {function(!Writer, number, T)|undefined}
|
||||
*/
|
||||
getEncoder() {
|
||||
return this.encoder_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the field, containing the original index entries and a
|
||||
* shallow copy of the cache.
|
||||
* @return {!Field}
|
||||
*/
|
||||
shallowCopy() {
|
||||
// Repeated fields are arrays in the cache.
|
||||
// We have to copy the array to make sure that modifications to a repeated
|
||||
// field (e.g. add) are not seen on a cloned accessor.
|
||||
const copiedCache = this.hasDecodedValue() ?
|
||||
(Array.isArray(this.getDecodedValue()) ? [...this.getDecodedValue()] :
|
||||
this.getDecodedValue()) :
|
||||
undefined;
|
||||
return new Field(this.getIndexArray(), copiedCache, this.getEncoder());
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
maybeRemoveIndexArray_() {
|
||||
checkState(
|
||||
this.encoder_ === undefined || this.decodedValue_ !== undefined,
|
||||
'Encoder exists but decoded value doesn\'t');
|
||||
if (this.encoder_ !== undefined) {
|
||||
this.indexArray_ = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports = {
|
||||
IndexEntry,
|
||||
Field,
|
||||
};
|
36
deps/protobuf/js/experimental/runtime/kernel/fixed32_test_pairs.js
vendored
Normal file
36
deps/protobuf/js/experimental/runtime/kernel/fixed32_test_pairs.js
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @fileoverview Test data for float encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.fixed32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, intValue: number, bufferDecoder:
|
||||
* !BufferDecoder}>}
|
||||
*/
|
||||
function getFixed32Pairs() {
|
||||
const fixed32Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
intValue: 0,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
intValue: 1,
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x00, 0x00, 0x00)
|
||||
},
|
||||
{
|
||||
name: 'max int 2^32 -1',
|
||||
intValue: Math.pow(2, 32) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF)
|
||||
},
|
||||
];
|
||||
return [...fixed32Pairs];
|
||||
}
|
||||
|
||||
exports = {getFixed32Pairs};
|
78
deps/protobuf/js/experimental/runtime/kernel/float_test_pairs.js
vendored
Normal file
78
deps/protobuf/js/experimental/runtime/kernel/float_test_pairs.js
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @fileoverview Test data for float encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.floatTestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, floatValue:number, bufferDecoder:
|
||||
* !BufferDecoder}>}
|
||||
*/
|
||||
function getFloatPairs() {
|
||||
const floatPairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
floatValue: 0,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'minus zero',
|
||||
floatValue: -0,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x80)
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
floatValue: 1,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0x3F)
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
floatValue: -1,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0xBF)
|
||||
},
|
||||
{
|
||||
name: 'two',
|
||||
floatValue: 2,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x40)
|
||||
},
|
||||
{
|
||||
name: 'max float32',
|
||||
floatValue: Math.pow(2, 127) * (2 - 1 / Math.pow(2, 23)),
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0x7F, 0x7F)
|
||||
},
|
||||
|
||||
{
|
||||
name: 'min float32',
|
||||
floatValue: 1 / Math.pow(2, 127 - 1),
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0x00)
|
||||
},
|
||||
|
||||
{
|
||||
name: 'Infinity',
|
||||
floatValue: Infinity,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0x7F)
|
||||
},
|
||||
{
|
||||
name: 'minus Infinity',
|
||||
floatValue: -Infinity,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x80, 0xFF)
|
||||
},
|
||||
{
|
||||
name: '1.5',
|
||||
floatValue: 1.5,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0xC0, 0x3F)
|
||||
},
|
||||
{
|
||||
name: '1.6',
|
||||
floatValue: 1.6,
|
||||
bufferDecoder: createBufferDecoder(0xCD, 0xCC, 0xCC, 0x3F)
|
||||
},
|
||||
];
|
||||
return [...floatPairs];
|
||||
}
|
||||
|
||||
exports = {getFloatPairs};
|
55
deps/protobuf/js/experimental/runtime/kernel/indexer.js
vendored
Normal file
55
deps/protobuf/js/experimental/runtime/kernel/indexer.js
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @fileoverview Utilities to index a binary proto by fieldnumbers without
|
||||
* relying on strutural proto information.
|
||||
*/
|
||||
goog.module('protobuf.binary.indexer');
|
||||
|
||||
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const WireType = goog.require('protobuf.binary.WireType');
|
||||
const {Field} = goog.require('protobuf.binary.field');
|
||||
const {checkCriticalState} = goog.require('protobuf.internal.checks');
|
||||
const {skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag');
|
||||
|
||||
/**
|
||||
* Appends a new entry in the index array for the given field number.
|
||||
* @param {!BinaryStorage<!Field>} storage
|
||||
* @param {number} fieldNumber
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} startIndex
|
||||
*/
|
||||
function addIndexEntry(storage, fieldNumber, wireType, startIndex) {
|
||||
const field = storage.get(fieldNumber);
|
||||
if (field !== undefined) {
|
||||
field.addIndexEntry(wireType, startIndex);
|
||||
} else {
|
||||
storage.set(fieldNumber, Field.fromFirstIndexEntry(wireType, startIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an index of field locations in a given binary protobuf.
|
||||
* @param {!BufferDecoder} bufferDecoder
|
||||
* @param {number|undefined} pivot
|
||||
* @return {!BinaryStorage<!Field>}
|
||||
* @package
|
||||
*/
|
||||
function buildIndex(bufferDecoder, pivot) {
|
||||
bufferDecoder.setCursor(bufferDecoder.startIndex());
|
||||
|
||||
const storage = new BinaryStorage(pivot);
|
||||
while (bufferDecoder.hasNext()) {
|
||||
const tag = bufferDecoder.getUnsignedVarint32();
|
||||
const wireType = tagToWireType(tag);
|
||||
const fieldNumber = tagToFieldNumber(tag);
|
||||
checkCriticalState(fieldNumber > 0, `Invalid field number ${fieldNumber}`);
|
||||
addIndexEntry(storage, fieldNumber, wireType, bufferDecoder.cursor());
|
||||
skipField(bufferDecoder, wireType, fieldNumber);
|
||||
}
|
||||
return storage;
|
||||
}
|
||||
|
||||
exports = {
|
||||
buildIndex,
|
||||
tagToWireType,
|
||||
};
|
334
deps/protobuf/js/experimental/runtime/kernel/indexer_test.js
vendored
Normal file
334
deps/protobuf/js/experimental/runtime/kernel/indexer_test.js
vendored
Normal file
@ -0,0 +1,334 @@
|
||||
/**
|
||||
* @fileoverview Tests for indexer.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.IndexerTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
// Note to the reader:
|
||||
// Since the index behavior changes with the checking level some of the tests
|
||||
// in this file have to know which checking level is enabled to make correct
|
||||
// assertions.
|
||||
// Test are run in all checking levels.
|
||||
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const WireType = goog.require('protobuf.binary.WireType');
|
||||
const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
|
||||
const {Field, IndexEntry} = goog.require('protobuf.binary.field');
|
||||
const {buildIndex} = goog.require('protobuf.binary.indexer');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* Returns the number of fields stored.
|
||||
*
|
||||
* @param {!BinaryStorage} storage
|
||||
* @return {number}
|
||||
*/
|
||||
function getStorageSize(storage) {
|
||||
let size = 0;
|
||||
storage.forEach(() => void size++);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
const PIVOT = 1;
|
||||
|
||||
/**
|
||||
* Asserts a single IndexEntry at a given field number.
|
||||
* @param {!BinaryStorage} storage
|
||||
* @param {number} fieldNumber
|
||||
* @param {...!IndexEntry} expectedEntries
|
||||
*/
|
||||
function assertStorageEntries(storage, fieldNumber, ...expectedEntries) {
|
||||
expect(getStorageSize(storage)).toBe(1);
|
||||
|
||||
const entryArray = storage.get(fieldNumber).getIndexArray();
|
||||
expect(entryArray).not.toBeUndefined();
|
||||
expect(entryArray.length).toBe(expectedEntries.length);
|
||||
|
||||
for (let i = 0; i < entryArray.length; i++) {
|
||||
const storageEntry = entryArray[i];
|
||||
const expectedEntry = expectedEntries[i];
|
||||
|
||||
expect(storageEntry).toBe(expectedEntry);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Indexer does', () => {
|
||||
it('return empty storage for empty array', () => {
|
||||
const storage = buildIndex(createBufferDecoder(), PIVOT);
|
||||
expect(storage).not.toBeNull();
|
||||
expect(getStorageSize(storage)).toBe(0);
|
||||
});
|
||||
|
||||
it('throw for null array', () => {
|
||||
expect(
|
||||
() => buildIndex(
|
||||
/** @type {!BufferDecoder} */ (/** @type {*} */ (null)), PIVOT))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it('fail for invalid wire type (6)', () => {
|
||||
expect(() => buildIndex(createBufferDecoder(0x0E, 0x01), PIVOT))
|
||||
.toThrowError('Unexpected wire type: 6');
|
||||
});
|
||||
|
||||
it('fail for invalid wire type (7)', () => {
|
||||
expect(() => buildIndex(createBufferDecoder(0x0F, 0x01), PIVOT))
|
||||
.toThrowError('Unexpected wire type: 7');
|
||||
});
|
||||
|
||||
it('index varint', () => {
|
||||
const data = createBufferDecoder(0x08, 0x01, 0x08, 0x01);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 1),
|
||||
Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 3));
|
||||
});
|
||||
|
||||
it('index varint with two bytes field number', () => {
|
||||
const data = createBufferDecoder(0xF8, 0x01, 0x01);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 31,
|
||||
Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 2));
|
||||
});
|
||||
|
||||
it('fail for varints that are longer than 10 bytes', () => {
|
||||
const data = createBufferDecoder(
|
||||
0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Index out of bounds: index: 12 size: 11');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.VARINT, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail for varints with no data', () => {
|
||||
const data = createBufferDecoder(0x08);
|
||||
expect(() => buildIndex(data, PIVOT)).toThrow();
|
||||
});
|
||||
|
||||
it('index fixed64', () => {
|
||||
const data = createBufferDecoder(
|
||||
/* first= */ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
/* second= */ 0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1),
|
||||
Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 10));
|
||||
});
|
||||
|
||||
it('fail for fixed64 data missing in input', () => {
|
||||
const data =
|
||||
createBufferDecoder(0x09, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Index out of bounds: index: 9 size: 8');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail for fixed64 tag that has no data after it', () => {
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
const data = createBufferDecoder(0x09);
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Index out of bounds: index: 9 size: 1');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const data = createBufferDecoder(0x09);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.FIXED64, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('index delimited', () => {
|
||||
const data = createBufferDecoder(
|
||||
/* first= */ 0x0A, 0x02, 0x00, 0x01, /* second= */ 0x0A, 0x02, 0x00,
|
||||
0x01);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 1),
|
||||
Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 5));
|
||||
});
|
||||
|
||||
it('fail for length deliimted field data missing in input', () => {
|
||||
const data = createBufferDecoder(0x0A, 0x04, 0x00, 0x01);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Index out of bounds: index: 6 size: 4');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.DELIMITED, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail for delimited tag that has no data after it', () => {
|
||||
const data = createBufferDecoder(0x0A);
|
||||
expect(() => buildIndex(data, PIVOT)).toThrow();
|
||||
});
|
||||
|
||||
it('index fixed32', () => {
|
||||
const data = createBufferDecoder(
|
||||
/* first= */ 0x0D, 0x01, 0x02, 0x03, 0x04, /* second= */ 0x0D, 0x01,
|
||||
0x02, 0x03, 0x04);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1),
|
||||
Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 6));
|
||||
});
|
||||
|
||||
it('fail for fixed32 data missing in input', () => {
|
||||
const data = createBufferDecoder(0x0D, 0x01, 0x02, 0x03);
|
||||
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Index out of bounds: index: 5 size: 4');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail for fixed32 tag that has no data after it', () => {
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
const data = createBufferDecoder(0x0D);
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Index out of bounds: index: 5 size: 1');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const data = createBufferDecoder(0x0D);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.FIXED32, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('index group', () => {
|
||||
const data = createBufferDecoder(
|
||||
/* first= */ 0x0B, 0x08, 0x01, 0x0C, /* second= */ 0x0B, 0x08, 0x01,
|
||||
0x0C);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1),
|
||||
Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 5));
|
||||
});
|
||||
|
||||
it('index group and skips inner group', () => {
|
||||
const data =
|
||||
createBufferDecoder(0x0B, 0x0B, 0x08, 0x01, 0x0C, 0x08, 0x01, 0x0C);
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
|
||||
});
|
||||
|
||||
it('fail on unmatched stop group', () => {
|
||||
const data = createBufferDecoder(0x0C, 0x01);
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Unexpected wire type: 4');
|
||||
});
|
||||
|
||||
it('fail for groups without matching stop group', () => {
|
||||
const data = createBufferDecoder(0x0B, 0x08, 0x01, 0x1C);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT))
|
||||
.toThrowError('Expected stop group for fieldnumber 1 not found.');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail for groups without stop group', () => {
|
||||
const data = createBufferDecoder(0x0B, 0x08, 0x01);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT)).toThrowError('No end group found.');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail for group tag that has no data after it', () => {
|
||||
const data = createBufferDecoder(0x0B);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => buildIndex(data, PIVOT)).toThrowError('No end group found.');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const storage = buildIndex(data, PIVOT);
|
||||
assertStorageEntries(
|
||||
storage, /* fieldNumber= */ 1,
|
||||
Field.encodeIndexEntry(WireType.START_GROUP, /* startIndex= */ 1));
|
||||
}
|
||||
});
|
||||
|
||||
it('index too large tag', () => {
|
||||
const data = createBufferDecoder(0xF8, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
expect(() => buildIndex(data, PIVOT)).toThrow();
|
||||
});
|
||||
|
||||
it('fail for varint tag that has no data after it', () => {
|
||||
const data = createBufferDecoder(0x08);
|
||||
expect(() => buildIndex(data, PIVOT)).toThrow();
|
||||
});
|
||||
});
|
71
deps/protobuf/js/experimental/runtime/kernel/int32_test_pairs.js
vendored
Normal file
71
deps/protobuf/js/experimental/runtime/kernel/int32_test_pairs.js
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @fileoverview Test data for int32 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.int32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, intValue:number, bufferDecoder:
|
||||
* !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getInt32Pairs() {
|
||||
const int32Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
intValue: 0,
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
intValue: 1,
|
||||
bufferDecoder: createBufferDecoder(0x01),
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
intValue: -1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F),
|
||||
// The writer will encode this with 64 bits, see below
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'minus one (64bits)',
|
||||
intValue: -1,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'max signed int 2^31 - 1',
|
||||
intValue: Math.pow(2, 31) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x07),
|
||||
|
||||
},
|
||||
{
|
||||
name: 'min signed int -2^31',
|
||||
intValue: -Math.pow(2, 31),
|
||||
bufferDecoder: createBufferDecoder(0x80, 0x80, 0x80, 0x80, 0x08),
|
||||
// The writer will encode this with 64 bits, see below
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'value min signed int -2^31 (64 bit)',
|
||||
intValue: -Math.pow(2, 31),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x80, 0x80, 0x80, 0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'errors out for 11 bytes',
|
||||
intValue: -1,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
|
||||
error: true,
|
||||
skip_writer: true,
|
||||
},
|
||||
];
|
||||
return [...int32Pairs];
|
||||
}
|
||||
|
||||
exports = {getInt32Pairs};
|
59
deps/protobuf/js/experimental/runtime/kernel/int64_test_pairs.js
vendored
Normal file
59
deps/protobuf/js/experimental/runtime/kernel/int64_test_pairs.js
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @fileoverview Test data for int64 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.int64TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, longValue: !Int64, bufferDecoder:
|
||||
* !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getInt64Pairs() {
|
||||
const int64Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
longValue: Int64.fromInt(0),
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
longValue: Int64.fromInt(1),
|
||||
bufferDecoder: createBufferDecoder(0x01),
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
longValue: Int64.fromInt(-1),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'max signed int 2^63 - 1',
|
||||
longValue: Int64.fromBits(0xFFFFFFFF, 0x7FFFFFFF),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F),
|
||||
|
||||
},
|
||||
{
|
||||
name: 'value min signed int -2^63 (64 bit)',
|
||||
longValue: Int64.fromBits(0xFFFFFFFF, 0xFFFFFFFF),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'errors out for 11 bytes',
|
||||
longValue: Int64.fromInt(-1),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
|
||||
error: true,
|
||||
skip_writer: true,
|
||||
},
|
||||
];
|
||||
return [...int64Pairs];
|
||||
}
|
||||
|
||||
exports = {getInt64Pairs};
|
24
deps/protobuf/js/experimental/runtime/kernel/internal_message.js
vendored
Normal file
24
deps/protobuf/js/experimental/runtime/kernel/internal_message.js
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @fileoverview Internal interface for messages implemented with the binary
|
||||
* kernel.
|
||||
*/
|
||||
goog.module('protobuf.binary.InternalMessage');
|
||||
|
||||
const Kernel = goog.requireType('protobuf.runtime.Kernel');
|
||||
|
||||
/**
|
||||
* Interface that needs to be implemented by messages implemented with the
|
||||
* binary kernel. This is an internal only interface and should be used only by
|
||||
* the classes in binary kernel.
|
||||
*
|
||||
* @interface
|
||||
*/
|
||||
class InternalMessage {
|
||||
/**
|
||||
* @package
|
||||
* @return {!Kernel}
|
||||
*/
|
||||
internalGetKernel() {}
|
||||
}
|
||||
|
||||
exports = InternalMessage;
|
4122
deps/protobuf/js/experimental/runtime/kernel/kernel.js
vendored
Normal file
4122
deps/protobuf/js/experimental/runtime/kernel/kernel.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
266
deps/protobuf/js/experimental/runtime/kernel/kernel_compatibility_test.js
vendored
Normal file
266
deps/protobuf/js/experimental/runtime/kernel/kernel_compatibility_test.js
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
/**
|
||||
* @fileoverview Tests to make sure Kernel can read data in a backward
|
||||
* compatible way even when protobuf schema changes according to the rules
|
||||
* defined in
|
||||
* https://developers.google.com/protocol-buffers/docs/proto#updating and
|
||||
* https://developers.google.com/protocol-buffers/docs/proto3#updating.
|
||||
*
|
||||
* third_party/protobuf/conformance/binary_json_conformance_suite.cc already
|
||||
* covers many compatibility tests, this file covers only the tests not covered
|
||||
* by binary_json_conformance_suite. Ultimately all of the tests in this file
|
||||
* should be moved to binary_json_conformance_suite.
|
||||
*/
|
||||
goog.module('protobuf.runtime.KernelCompatibilityTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
const TestMessage = goog.require('protobuf.testing.binary.TestMessage');
|
||||
const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
|
||||
|
||||
/**
|
||||
* @param {...number} bytes
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
function createArrayBuffer(...bytes) {
|
||||
return new Uint8Array(bytes).buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Unicode character codes of a string.
|
||||
* @param {string} str
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
function getCharacterCodes(str) {
|
||||
return Array.from(str, (c) => c.charCodeAt(0));
|
||||
}
|
||||
|
||||
describe('optional -> repeated compatibility', () => {
|
||||
it('is maintained for scalars', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setInt32(1, 1);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0x8, 0x1));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getRepeatedInt32Size(1)).toEqual(1);
|
||||
expect(newAccessor.getRepeatedInt32Element(1, 0)).toEqual(1);
|
||||
});
|
||||
|
||||
it('is maintained for messages', () => {
|
||||
const message = new TestMessage(Kernel.createEmpty());
|
||||
message.setInt32(1, 1);
|
||||
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setMessage(1, message);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getRepeatedMessageSize(1, TestMessage.instanceCreator))
|
||||
.toEqual(1);
|
||||
expect(
|
||||
newAccessor.getRepeatedMessageElement(1, TestMessage.instanceCreator, 0)
|
||||
.serialize())
|
||||
.toEqual(message.serialize());
|
||||
});
|
||||
|
||||
it('is maintained for bytes', () => {
|
||||
const message = new TestMessage(Kernel.createEmpty());
|
||||
message.setInt32(1, 1);
|
||||
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setBytes(
|
||||
1, ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB)));
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0xA, 0xB));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getRepeatedBytesSize(1)).toEqual(1);
|
||||
expect(newAccessor.getRepeatedBoolElement(1, 0))
|
||||
.toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB)));
|
||||
});
|
||||
|
||||
it('is maintained for strings', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setString(1, 'hello');
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(0xA, 0x5, 0x68, 0x65, 0x6C, 0x6C, 0x6F));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getRepeatedStringSize(1)).toEqual(1);
|
||||
expect(newAccessor.getRepeatedStringElement(1, 0)).toEqual('hello');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Kernel repeated -> optional compatibility', () => {
|
||||
it('is maintained for unpacked scalars', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.addUnpackedInt32Element(1, 0);
|
||||
oldAccessor.addUnpackedInt32Element(1, 1);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0x8, 0x0, 0x8, 0x1));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getInt32WithDefault(1)).toEqual(1);
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
// repeated -> optional transformation is not supported for packed fields yet:
|
||||
// go/proto-schema-repeated
|
||||
it('is not maintained for packed scalars', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.addPackedInt32Element(1, 0);
|
||||
oldAccessor.addPackedInt32Element(1, 1);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x0, 0x1));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => newAccessor.getInt32WithDefault(1)).toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
it('is maintained for messages', () => {
|
||||
const message1 = new TestMessage(Kernel.createEmpty());
|
||||
message1.setInt32(1, 1);
|
||||
const message2 = new TestMessage(Kernel.createEmpty());
|
||||
message2.setInt32(1, 2);
|
||||
message2.setInt32(2, 3);
|
||||
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.addRepeatedMessageElement(
|
||||
1, message1, TestMessage.instanceCreator);
|
||||
oldAccessor.addRepeatedMessageElement(
|
||||
1, message2, TestMessage.instanceCreator);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(
|
||||
0xA, 0x2, 0x8, 0x1, 0xA, 0x4, 0x8, 0x2, 0x10, 0x3));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
// Values from message1 and message2 have been merged
|
||||
const newMessage = newAccessor.getMessage(1, TestMessage.instanceCreator);
|
||||
expect(newMessage.getRepeatedInt32Size(1)).toEqual(2);
|
||||
expect(newMessage.getRepeatedInt32Element(1, 0)).toEqual(1);
|
||||
expect(newMessage.getRepeatedInt32Element(1, 1)).toEqual(2);
|
||||
expect(newMessage.getInt32WithDefault(2)).toEqual(3);
|
||||
expect(newMessage.serialize())
|
||||
.toEqual(createArrayBuffer(0x8, 0x1, 0x8, 0x2, 0x10, 0x3));
|
||||
});
|
||||
|
||||
it('is maintained for bytes', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.addRepeatedBytesElement(
|
||||
1, ByteString.fromArrayBuffer(createArrayBuffer(0xA, 0xB)));
|
||||
oldAccessor.addRepeatedBytesElement(
|
||||
1, ByteString.fromArrayBuffer(createArrayBuffer(0xC, 0xD)));
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(0xA, 0x2, 0xA, 0xB, 0xA, 0x2, 0xC, 0xD));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getBytesWithDefault(1))
|
||||
.toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0xC, 0xD)));
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
it('is maintained for strings', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.addRepeatedStringElement(1, 'hello');
|
||||
oldAccessor.addRepeatedStringElement(1, 'world');
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(
|
||||
0xA, 0x5, ...getCharacterCodes('hello'), 0xA, 0x5,
|
||||
...getCharacterCodes('world')));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getStringWithDefault(1)).toEqual('world');
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Type change', () => {
|
||||
it('is supported for fixed32 -> sfixed32', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setFixed32(1, 4294967295);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(0xD, 0xFF, 0xFF, 0xFF, 0xFF));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getSfixed32WithDefault(1)).toEqual(-1);
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
it('is supported for sfixed32 -> fixed32', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setSfixed32(1, -1);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(0xD, 0xFF, 0xFF, 0xFF, 0xFF));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getFixed32WithDefault(1)).toEqual(4294967295);
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
it('is supported for fixed64 -> sfixed64', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setFixed64(1, Int64.fromHexString('0xFFFFFFFFFFFFFFFF'));
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(
|
||||
0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getSfixed64WithDefault(1)).toEqual(Int64.fromInt(-1));
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
it('is supported for sfixed64 -> fixed64', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setSfixed64(1, Int64.fromInt(-1));
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData)
|
||||
.toEqual(createArrayBuffer(
|
||||
0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getFixed64WithDefault(1))
|
||||
.toEqual(Int64.fromHexString('0xFFFFFFFFFFFFFFFF'));
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
it('is supported for bytes -> message', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
oldAccessor.setBytes(
|
||||
1, ByteString.fromArrayBuffer(createArrayBuffer(0x8, 0x1)));
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
const message = newAccessor.getMessage(1, TestMessage.instanceCreator);
|
||||
expect(message.getInt32WithDefault(1)).toEqual(1);
|
||||
expect(message.serialize()).toEqual(createArrayBuffer(0x8, 0x1));
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
|
||||
it('is supported for message -> bytes', () => {
|
||||
const oldAccessor = Kernel.createEmpty();
|
||||
const message = new TestMessage(Kernel.createEmpty());
|
||||
message.setInt32(1, 1);
|
||||
oldAccessor.setMessage(1, message);
|
||||
const serializedData = oldAccessor.serialize();
|
||||
expect(serializedData).toEqual(createArrayBuffer(0xA, 0x2, 0x8, 0x1));
|
||||
|
||||
const newAccessor = Kernel.fromArrayBuffer(serializedData);
|
||||
expect(newAccessor.getBytesWithDefault(1))
|
||||
.toEqual(ByteString.fromArrayBuffer(createArrayBuffer(0x8, 0x1)));
|
||||
expect(newAccessor.serialize()).toEqual(serializedData);
|
||||
});
|
||||
});
|
7807
deps/protobuf/js/experimental/runtime/kernel/kernel_repeated_test.js
vendored
Normal file
7807
deps/protobuf/js/experimental/runtime/kernel/kernel_repeated_test.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2329
deps/protobuf/js/experimental/runtime/kernel/kernel_test.js
vendored
Normal file
2329
deps/protobuf/js/experimental/runtime/kernel/kernel_test.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
285
deps/protobuf/js/experimental/runtime/kernel/message_set.js
vendored
Normal file
285
deps/protobuf/js/experimental/runtime/kernel/message_set.js
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
##########################################################
|
||||
# #
|
||||
# __ __ _____ _ _ _____ _ _ _____ #
|
||||
# \ \ / /\ | __ \| \ | |_ _| \ | |/ ____| #
|
||||
# \ \ /\ / / \ | |__) | \| | | | | \| | | __ #
|
||||
# \ \/ \/ / /\ \ | _ /| . ` | | | | . ` | | |_ | #
|
||||
# \ /\ / ____ \| | \ \| |\ |_| |_| |\ | |__| | #
|
||||
# \/ \/_/ \_\_| \_\_| \_|_____|_| \_|\_____| #
|
||||
# #
|
||||
# #
|
||||
##########################################################
|
||||
# Do not use this class in your code. This class purely #
|
||||
# exists to make proto code generation easier. #
|
||||
##########################################################
|
||||
*/
|
||||
goog.module('protobuf.runtime.MessageSet');
|
||||
|
||||
const InternalMessage = goog.require('protobuf.binary.InternalMessage');
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
|
||||
// These are the tags for the old MessageSet format, which was defined as:
|
||||
// message MessageSet {
|
||||
// repeated group Item = 1 {
|
||||
// required uint32 type_id = 2;
|
||||
// optional bytes message = 3;
|
||||
// }
|
||||
// }
|
||||
/** @const {number} */
|
||||
const MSET_GROUP_FIELD_NUMBER = 1;
|
||||
/** @const {number} */
|
||||
const MSET_TYPE_ID_FIELD_NUMBER = 2;
|
||||
/** @const {number} */
|
||||
const MSET_MESSAGE_FIELD_NUMBER = 3;
|
||||
|
||||
/**
|
||||
* @param {!Kernel} kernel
|
||||
* @return {!Map<number, !Item>}
|
||||
*/
|
||||
function createItemMap(kernel) {
|
||||
const itemMap = new Map();
|
||||
let totalCount = 0;
|
||||
for (const item of kernel.getRepeatedGroupIterable(
|
||||
MSET_GROUP_FIELD_NUMBER, Item.fromKernel)) {
|
||||
itemMap.set(item.getTypeId(), item);
|
||||
totalCount++;
|
||||
}
|
||||
|
||||
// Normalize the entries.
|
||||
if (totalCount > itemMap.size) {
|
||||
writeItemMap(kernel, itemMap);
|
||||
}
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Kernel} kernel
|
||||
* @param {!Map<number, !Item>} itemMap
|
||||
*/
|
||||
function writeItemMap(kernel, itemMap) {
|
||||
kernel.setRepeatedGroupIterable(MSET_GROUP_FIELD_NUMBER, itemMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* @implements {InternalMessage}
|
||||
* @final
|
||||
*/
|
||||
class MessageSet {
|
||||
/**
|
||||
* @param {!Kernel} kernel
|
||||
* @return {!MessageSet}
|
||||
*/
|
||||
static fromKernel(kernel) {
|
||||
const itemMap = createItemMap(kernel);
|
||||
return new MessageSet(kernel, itemMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!MessageSet}
|
||||
*/
|
||||
static createEmpty() {
|
||||
return MessageSet.fromKernel(Kernel.createEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Kernel} kernel
|
||||
* @param {!Map<number, !Item>} itemMap
|
||||
* @private
|
||||
*/
|
||||
constructor(kernel, itemMap) {
|
||||
/** @const {!Kernel} @private */
|
||||
this.kernel_ = kernel;
|
||||
/** @const {!Map<number, !Item>} @private */
|
||||
this.itemMap_ = itemMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// code helpers for code gen
|
||||
|
||||
/**
|
||||
* @param {number} typeId
|
||||
* @param {function(!Kernel):T} instanceCreator
|
||||
* @param {number=} pivot
|
||||
* @return {?T}
|
||||
* @template T
|
||||
*/
|
||||
getMessageOrNull(typeId, instanceCreator, pivot) {
|
||||
const item = this.itemMap_.get(typeId);
|
||||
return item ? item.getMessageOrNull(instanceCreator, pivot) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} typeId
|
||||
* @param {function(!Kernel):T} instanceCreator
|
||||
* @param {number=} pivot
|
||||
* @return {T}
|
||||
* @template T
|
||||
*/
|
||||
getMessageAttach(typeId, instanceCreator, pivot) {
|
||||
let item = this.itemMap_.get(typeId);
|
||||
if (item) {
|
||||
return item.getMessageAttach(instanceCreator, pivot);
|
||||
}
|
||||
const message = instanceCreator(Kernel.createEmpty());
|
||||
this.setMessage(typeId, message);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} typeId
|
||||
* @param {number=} pivot
|
||||
* @return {?Kernel}
|
||||
*/
|
||||
getMessageAccessorOrNull(typeId, pivot) {
|
||||
const item = this.itemMap_.get(typeId);
|
||||
return item ? item.getMessageAccessorOrNull(pivot) : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} typeId
|
||||
*/
|
||||
clearMessage(typeId) {
|
||||
if (this.itemMap_.delete(typeId)) {
|
||||
writeItemMap(this.kernel_, this.itemMap_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} typeId
|
||||
* @return {boolean}
|
||||
*/
|
||||
hasMessage(typeId) {
|
||||
return this.itemMap_.has(typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} typeId
|
||||
* @param {!InternalMessage} value
|
||||
*/
|
||||
setMessage(typeId, value) {
|
||||
const item = this.itemMap_.get(typeId);
|
||||
if (item) {
|
||||
item.setMessage(value);
|
||||
} else {
|
||||
this.itemMap_.set(typeId, Item.create(typeId, value));
|
||||
writeItemMap(this.kernel_, this.itemMap_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Kernel}
|
||||
* @override
|
||||
*/
|
||||
internalGetKernel() {
|
||||
return this.kernel_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @implements {InternalMessage}
|
||||
* @final
|
||||
*/
|
||||
class Item {
|
||||
/**
|
||||
* @param {number} typeId
|
||||
* @param {!InternalMessage} message
|
||||
* @return {!Item}
|
||||
*/
|
||||
static create(typeId, message) {
|
||||
const messageSet = Item.fromKernel(Kernel.createEmpty());
|
||||
messageSet.setTypeId_(typeId);
|
||||
messageSet.setMessage(message);
|
||||
return messageSet;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {!Kernel} kernel
|
||||
* @return {!Item}
|
||||
*/
|
||||
static fromKernel(kernel) {
|
||||
return new Item(kernel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Kernel} kernel
|
||||
* @private
|
||||
*/
|
||||
constructor(kernel) {
|
||||
/** @const {!Kernel} @private */
|
||||
this.kernel_ = kernel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function(!Kernel):T} instanceCreator
|
||||
* @param {number=} pivot
|
||||
* @return {T}
|
||||
* @template T
|
||||
*/
|
||||
getMessage(instanceCreator, pivot) {
|
||||
return this.kernel_.getMessage(
|
||||
MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function(!Kernel):T} instanceCreator
|
||||
* @param {number=} pivot
|
||||
* @return {?T}
|
||||
* @template T
|
||||
*/
|
||||
getMessageOrNull(instanceCreator, pivot) {
|
||||
return this.kernel_.getMessageOrNull(
|
||||
MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {function(!Kernel):T} instanceCreator
|
||||
* @param {number=} pivot
|
||||
* @return {T}
|
||||
* @template T
|
||||
*/
|
||||
getMessageAttach(instanceCreator, pivot) {
|
||||
return this.kernel_.getMessageAttach(
|
||||
MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number=} pivot
|
||||
* @return {?Kernel}
|
||||
*/
|
||||
getMessageAccessorOrNull(pivot) {
|
||||
return this.kernel_.getMessageAccessorOrNull(
|
||||
MSET_MESSAGE_FIELD_NUMBER, pivot);
|
||||
}
|
||||
|
||||
/** @param {!InternalMessage} value */
|
||||
setMessage(value) {
|
||||
this.kernel_.setMessage(MSET_MESSAGE_FIELD_NUMBER, value);
|
||||
}
|
||||
|
||||
/** @return {number} */
|
||||
getTypeId() {
|
||||
return this.kernel_.getUint32WithDefault(MSET_TYPE_ID_FIELD_NUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
setTypeId_(value) {
|
||||
this.kernel_.setUint32(MSET_TYPE_ID_FIELD_NUMBER, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Kernel}
|
||||
* @override
|
||||
*/
|
||||
internalGetKernel() {
|
||||
return this.kernel_;
|
||||
}
|
||||
}
|
||||
|
||||
exports = MessageSet;
|
262
deps/protobuf/js/experimental/runtime/kernel/message_set_test.js
vendored
Normal file
262
deps/protobuf/js/experimental/runtime/kernel/message_set_test.js
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
/**
|
||||
* @fileoverview Tests for message_set.js.
|
||||
*/
|
||||
goog.module('protobuf.runtime.MessageSetTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
const Kernel = goog.require('protobuf.runtime.Kernel');
|
||||
const MessageSet = goog.require('protobuf.runtime.MessageSet');
|
||||
const TestMessage = goog.require('protobuf.testing.binary.TestMessage');
|
||||
|
||||
/**
|
||||
* @param {...number} bytes
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
function createArrayBuffer(...bytes) {
|
||||
return new Uint8Array(bytes).buffer;
|
||||
}
|
||||
|
||||
describe('MessageSet does', () => {
|
||||
it('returns no messages for empty set', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator))
|
||||
.toBeNull();
|
||||
});
|
||||
|
||||
it('returns no kernel for empty set', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns message that has been set', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
const message = TestMessage.createEmpty();
|
||||
messageSet.setMessage(12345, message);
|
||||
expect(messageSet.getMessageOrNull(12345, TestMessage.instanceCreator))
|
||||
.toBe(message);
|
||||
});
|
||||
|
||||
it('returns null for cleared message', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
const message = TestMessage.createEmpty();
|
||||
messageSet.setMessage(12345, message);
|
||||
messageSet.clearMessage(12345);
|
||||
expect(messageSet.getMessageAccessorOrNull(12345)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns false for not present message', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
expect(messageSet.hasMessage(12345)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true for present message', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
const message = TestMessage.createEmpty();
|
||||
messageSet.setMessage(12345, message);
|
||||
expect(messageSet.hasMessage(12345)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for cleared message', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
const message = TestMessage.createEmpty();
|
||||
messageSet.setMessage(12345, message);
|
||||
messageSet.clearMessage(12345);
|
||||
expect(messageSet.hasMessage(12345)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for cleared message without it being present', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
messageSet.clearMessage(12345);
|
||||
expect(messageSet.hasMessage(12345)).toBe(false);
|
||||
});
|
||||
|
||||
const createMessageSet = () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
const message = TestMessage.createEmpty();
|
||||
message.setInt32(1, 2);
|
||||
messageSet.setMessage(12345, message);
|
||||
|
||||
|
||||
const parsedKernel =
|
||||
Kernel.fromArrayBuffer(messageSet.internalGetKernel().serialize());
|
||||
return MessageSet.fromKernel(parsedKernel);
|
||||
};
|
||||
|
||||
it('pass through pivot for getMessageOrNull', () => {
|
||||
const messageSet = createMessageSet();
|
||||
const message =
|
||||
messageSet.getMessageOrNull(12345, TestMessage.instanceCreator, 2);
|
||||
expect(message.internalGetKernel().getPivot()).toBe(2);
|
||||
});
|
||||
|
||||
it('pass through pivot for getMessageAttach', () => {
|
||||
const messageSet = createMessageSet();
|
||||
const message =
|
||||
messageSet.getMessageAttach(12345, TestMessage.instanceCreator, 2);
|
||||
expect(message.internalGetKernel().getPivot()).toBe(2);
|
||||
});
|
||||
|
||||
it('pass through pivot for getMessageAccessorOrNull', () => {
|
||||
const messageSet = createMessageSet();
|
||||
const kernel = messageSet.getMessageAccessorOrNull(12345, 2);
|
||||
expect(kernel.getPivot()).toBe(2);
|
||||
});
|
||||
|
||||
it('pick the last value in the stream', () => {
|
||||
const arrayBuffer = createArrayBuffer(
|
||||
0x52, // Tag (field:10, length delimited)
|
||||
0x14, // Length of 20 bytes
|
||||
0x0B, // Start group fieldnumber 1
|
||||
0x10, // Tag (field 2, varint)
|
||||
0xB9, // 12345
|
||||
0x60, // 12345
|
||||
0x1A, // Tag (field 3, length delimited)
|
||||
0x03, // length 3
|
||||
0xA0, // Tag (fieldnumber 20, varint)
|
||||
0x01, // Tag (fieldnumber 20, varint)
|
||||
0x1E, // 30
|
||||
0x0C, // Stop Group field number 1
|
||||
// second group
|
||||
0x0B, // Start group fieldnumber 1
|
||||
0x10, // Tag (field 2, varint)
|
||||
0xB9, // 12345
|
||||
0x60, // 12345
|
||||
0x1A, // Tag (field 3, length delimited)
|
||||
0x03, // length 3
|
||||
0xA0, // Tag (fieldnumber 20, varint)
|
||||
0x01, // Tag (fieldnumber 20, varint)
|
||||
0x01, // 1
|
||||
0x0C // Stop Group field number 1
|
||||
);
|
||||
|
||||
const outerMessage = Kernel.fromArrayBuffer(arrayBuffer);
|
||||
|
||||
const messageSet = outerMessage.getMessage(10, MessageSet.fromKernel);
|
||||
|
||||
const message =
|
||||
messageSet.getMessageOrNull(12345, TestMessage.instanceCreator);
|
||||
expect(message.getInt32WithDefault(20)).toBe(1);
|
||||
});
|
||||
|
||||
it('removes duplicates when read', () => {
|
||||
const arrayBuffer = createArrayBuffer(
|
||||
0x52, // Tag (field:10, length delimited)
|
||||
0x14, // Length of 20 bytes
|
||||
0x0B, // Start group fieldnumber 1
|
||||
0x10, // Tag (field 2, varint)
|
||||
0xB9, // 12345
|
||||
0x60, // 12345
|
||||
0x1A, // Tag (field 3, length delimited)
|
||||
0x03, // length 3
|
||||
0xA0, // Tag (fieldnumber 20, varint)
|
||||
0x01, // Tag (fieldnumber 20, varint)
|
||||
0x1E, // 30
|
||||
0x0C, // Stop Group field number 1
|
||||
// second group
|
||||
0x0B, // Start group fieldnumber 1
|
||||
0x10, // Tag (field 2, varint)
|
||||
0xB9, // 12345
|
||||
0x60, // 12345
|
||||
0x1A, // Tag (field 3, length delimited)
|
||||
0x03, // length 3
|
||||
0xA0, // Tag (fieldnumber 20, varint)
|
||||
0x01, // Tag (fieldnumber 20, varint)
|
||||
0x01, // 1
|
||||
0x0C // Stop Group field number 1
|
||||
);
|
||||
|
||||
|
||||
const outerMessage = Kernel.fromArrayBuffer(arrayBuffer);
|
||||
outerMessage.getMessageAttach(10, MessageSet.fromKernel);
|
||||
|
||||
expect(outerMessage.serialize())
|
||||
.toEqual(createArrayBuffer(
|
||||
0x52, // Tag (field:10, length delimited)
|
||||
0x0A, // Length of 10 bytes
|
||||
0x0B, // Start group fieldnumber 1
|
||||
0x10, // Tag (field 2, varint)
|
||||
0xB9, // 12345
|
||||
0x60, // 12345
|
||||
0x1A, // Tag (field 3, length delimited)
|
||||
0x03, // length 3
|
||||
0xA0, // Tag (fieldnumber 20, varint)
|
||||
0x01, // Tag (fieldnumber 20, varint)
|
||||
0x01, // 1
|
||||
0x0C // Stop Group field number 1
|
||||
));
|
||||
});
|
||||
|
||||
it('allow for large typeIds', () => {
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
const message = TestMessage.createEmpty();
|
||||
messageSet.setMessage(0xFFFFFFFE >>> 0, message);
|
||||
expect(messageSet.hasMessage(0xFFFFFFFE >>> 0)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Optional MessageSet does', () => {
|
||||
// message Bar {
|
||||
// optional MessageSet mset = 10;
|
||||
//}
|
||||
//
|
||||
// message Foo {
|
||||
// extend proto2.bridge.MessageSet {
|
||||
// optional Foo message_set_extension = 12345;
|
||||
// }
|
||||
// optional int32 f20 = 20;
|
||||
//}
|
||||
|
||||
it('encode as a field', () => {
|
||||
const fooMessage = Kernel.createEmpty();
|
||||
fooMessage.setInt32(20, 30);
|
||||
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage));
|
||||
|
||||
const barMessage = Kernel.createEmpty();
|
||||
barMessage.setMessage(10, messageSet);
|
||||
|
||||
expect(barMessage.serialize())
|
||||
.toEqual(createArrayBuffer(
|
||||
0x52, // Tag (field:10, length delimited)
|
||||
0x0A, // Length of 10 bytes
|
||||
0x0B, // Start group fieldnumber 1
|
||||
0x10, // Tag (field 2, varint)
|
||||
0xB9, // 12345
|
||||
0x60, // 12345
|
||||
0x1A, // Tag (field 3, length delimited)
|
||||
0x03, // length 3
|
||||
0xA0, // Tag (fieldnumber 20, varint)
|
||||
0x01, // Tag (fieldnumber 20, varint)
|
||||
0x1E, // 30
|
||||
0x0C // Stop Group field number 1
|
||||
));
|
||||
});
|
||||
|
||||
it('deserializes', () => {
|
||||
const fooMessage = Kernel.createEmpty();
|
||||
fooMessage.setInt32(20, 30);
|
||||
|
||||
const messageSet = MessageSet.createEmpty();
|
||||
messageSet.setMessage(12345, TestMessage.instanceCreator(fooMessage));
|
||||
|
||||
|
||||
const barMessage = Kernel.createEmpty();
|
||||
barMessage.setMessage(10, messageSet);
|
||||
|
||||
const arrayBuffer = barMessage.serialize();
|
||||
|
||||
const barMessageParsed = Kernel.fromArrayBuffer(arrayBuffer);
|
||||
expect(barMessageParsed.hasFieldNumber(10)).toBe(true);
|
||||
|
||||
const messageSetParsed =
|
||||
barMessageParsed.getMessage(10, MessageSet.fromKernel);
|
||||
|
||||
const fooMessageParsed =
|
||||
messageSetParsed.getMessageOrNull(12345, TestMessage.instanceCreator)
|
||||
.internalGetKernel();
|
||||
|
||||
expect(fooMessageParsed.getInt32WithDefault(20)).toBe(30);
|
||||
});
|
||||
});
|
59
deps/protobuf/js/experimental/runtime/kernel/packed_bool_test_pairs.js
vendored
Normal file
59
deps/protobuf/js/experimental/runtime/kernel/packed_bool_test_pairs.js
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
goog.module('protobuf.binary.packedBoolTestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed bool values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, boolValues: !Array<boolean>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedBoolPairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
boolValues: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
boolValues: [true],
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'single multi-bytes value',
|
||||
boolValues: [true],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x80, 0x01),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
boolValues: [true, false],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'multiple multi-bytes values',
|
||||
boolValues: [true, false],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x0C, // length
|
||||
0x80,
|
||||
0x80,
|
||||
0x80,
|
||||
0x80,
|
||||
0x80,
|
||||
0x01, // true
|
||||
0x80,
|
||||
0x80,
|
||||
0x80,
|
||||
0x80,
|
||||
0x80,
|
||||
0x00, // false
|
||||
),
|
||||
skip_writer: true,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedBoolPairs};
|
52
deps/protobuf/js/experimental/runtime/kernel/packed_double_test_pairs.js
vendored
Normal file
52
deps/protobuf/js/experimental/runtime/kernel/packed_double_test_pairs.js
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
goog.module('protobuf.binary.packedDoubleTestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed double values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, doubleValues: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedDoublePairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
doubleValues: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
doubleValues: [1],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
doubleValues: [1, 0],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x10, // length
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0xF0,
|
||||
0x3F, // 1
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00, // 0
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedDoublePairs};
|
34
deps/protobuf/js/experimental/runtime/kernel/packed_fixed32_test_pairs.js
vendored
Normal file
34
deps/protobuf/js/experimental/runtime/kernel/packed_fixed32_test_pairs.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
goog.module('protobuf.binary.packedFixed32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed fixed32 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, fixed32Values: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedFixed32Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
fixed32Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
fixed32Values: [1],
|
||||
bufferDecoder: createBufferDecoder(0x04, 0x01, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
fixed32Values: [1, 0],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedFixed32Pairs};
|
34
deps/protobuf/js/experimental/runtime/kernel/packed_float_test_pairs.js
vendored
Normal file
34
deps/protobuf/js/experimental/runtime/kernel/packed_float_test_pairs.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
goog.module('protobuf.binary.packedFloatTestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, floatValues: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedFloatPairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
floatValues: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
floatValues: [1],
|
||||
bufferDecoder: createBufferDecoder(0x04, 0x00, 0x00, 0x80, 0x3F),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
floatValues: [1, 0],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x08, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedFloatPairs};
|
33
deps/protobuf/js/experimental/runtime/kernel/packed_int32_test_pairs.js
vendored
Normal file
33
deps/protobuf/js/experimental/runtime/kernel/packed_int32_test_pairs.js
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
goog.module('protobuf.binary.packedInt32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed int32 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, int32Values: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedInt32Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
int32Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
int32Values: [1],
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
int32Values: [1, 0],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedInt32Pairs};
|
34
deps/protobuf/js/experimental/runtime/kernel/packed_int64_test_pairs.js
vendored
Normal file
34
deps/protobuf/js/experimental/runtime/kernel/packed_int64_test_pairs.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
goog.module('protobuf.binary.packedInt64TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed int64 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, int64Values: !Array<!Int64>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedInt64Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
int64Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
int64Values: [Int64.fromInt(1)],
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
int64Values: [Int64.fromInt(1), Int64.fromInt(0)],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedInt64Pairs};
|
34
deps/protobuf/js/experimental/runtime/kernel/packed_sfixed32_test_pairs.js
vendored
Normal file
34
deps/protobuf/js/experimental/runtime/kernel/packed_sfixed32_test_pairs.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
goog.module('protobuf.binary.packedSfixed32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed sfixed32 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, sfixed32Values: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedSfixed32Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
sfixed32Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
sfixed32Values: [1],
|
||||
bufferDecoder: createBufferDecoder(0x04, 0x01, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
sfixed32Values: [1, 0],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedSfixed32Pairs};
|
53
deps/protobuf/js/experimental/runtime/kernel/packed_sfixed64_test_pairs.js
vendored
Normal file
53
deps/protobuf/js/experimental/runtime/kernel/packed_sfixed64_test_pairs.js
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
goog.module('protobuf.binary.packedSfixed64TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed sfixed64 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, sfixed64Values: !Array<!Int64>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedSfixed64Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
sfixed64Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
sfixed64Values: [Int64.fromInt(1)],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
sfixed64Values: [Int64.fromInt(1), Int64.fromInt(0)],
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0x10, // length
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00, // 1
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00, // 2
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedSfixed64Pairs};
|
33
deps/protobuf/js/experimental/runtime/kernel/packed_sint32_test_pairs.js
vendored
Normal file
33
deps/protobuf/js/experimental/runtime/kernel/packed_sint32_test_pairs.js
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
goog.module('protobuf.binary.packedSint32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed sint32 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, sint32Values: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedSint32Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
sint32Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
sint32Values: [-1],
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
sint32Values: [-1, 0],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedSint32Pairs};
|
34
deps/protobuf/js/experimental/runtime/kernel/packed_sint64_test_pairs.js
vendored
Normal file
34
deps/protobuf/js/experimental/runtime/kernel/packed_sint64_test_pairs.js
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
goog.module('protobuf.binary.packedSint64TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed sint64 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, sint64Values: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedSint64Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
sint64Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
sint64Values: [Int64.fromInt(-1)],
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
sint64Values: [Int64.fromInt(-1), Int64.fromInt(0)],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedSint64Pairs};
|
33
deps/protobuf/js/experimental/runtime/kernel/packed_uint32_test_pairs.js
vendored
Normal file
33
deps/protobuf/js/experimental/runtime/kernel/packed_uint32_test_pairs.js
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
goog.module('protobuf.binary.packedUint32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of packed uint32 values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, uint32Values: !Array<number>,
|
||||
* bufferDecoder: !BufferDecoder, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getPackedUint32Pairs() {
|
||||
return [
|
||||
{
|
||||
name: 'empty value',
|
||||
uint32Values: [],
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'single value',
|
||||
uint32Values: [1],
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x01),
|
||||
},
|
||||
{
|
||||
name: 'multiple values',
|
||||
uint32Values: [1, 0],
|
||||
bufferDecoder: createBufferDecoder(0x02, 0x01, 0x00),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
exports = {getPackedUint32Pairs};
|
364
deps/protobuf/js/experimental/runtime/kernel/reader.js
vendored
Normal file
364
deps/protobuf/js/experimental/runtime/kernel/reader.js
vendored
Normal file
@ -0,0 +1,364 @@
|
||||
/**
|
||||
* @fileoverview Helper methods for reading data from the binary wire format.
|
||||
*/
|
||||
goog.module('protobuf.binary.reader');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {checkState} = goog.require('protobuf.internal.checks');
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* OPTIONAL FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads a boolean value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {boolean}
|
||||
* @package
|
||||
*/
|
||||
function readBool(bufferDecoder, start) {
|
||||
const {lowBits, highBits} = bufferDecoder.getVarint(start);
|
||||
return lowBits !== 0 || highBits !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a ByteString value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!ByteString}
|
||||
* @package
|
||||
*/
|
||||
function readBytes(bufferDecoder, start) {
|
||||
return readDelimited(bufferDecoder, start).asByteString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a int32 value from the binary bytes encoded as varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readInt32(bufferDecoder, start) {
|
||||
// Negative 32 bit integers are encoded with 64 bit values.
|
||||
// Clients are expected to truncate back to 32 bits.
|
||||
// This is why we are dropping the upper bytes here.
|
||||
return bufferDecoder.getUnsignedVarint32At(start) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a int32 value from the binary bytes encoded as varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Int64}
|
||||
* @package
|
||||
*/
|
||||
function readInt64(bufferDecoder, start) {
|
||||
const {lowBits, highBits} = bufferDecoder.getVarint(start);
|
||||
return Int64.fromBits(lowBits, highBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a fixed int32 value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readFixed32(bufferDecoder, start) {
|
||||
return bufferDecoder.getUint32(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a float value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readFloat(bufferDecoder, start) {
|
||||
return bufferDecoder.getFloat32(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a fixed int64 value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Int64}
|
||||
* @package
|
||||
*/
|
||||
function readSfixed64(bufferDecoder, start) {
|
||||
const lowBits = bufferDecoder.getInt32(start);
|
||||
const highBits = bufferDecoder.getInt32(start + 4);
|
||||
return Int64.fromBits(lowBits, highBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a sint64 value from the binary bytes encoded as varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Int64}
|
||||
* @package
|
||||
*/
|
||||
function readSint64(bufferDecoder, start) {
|
||||
const {lowBits, highBits} = bufferDecoder.getVarint(start);
|
||||
const sign = -(lowBits & 0x01);
|
||||
const decodedLowerBits = ((lowBits >>> 1) | (highBits & 0x01) << 31) ^ sign;
|
||||
const decodedUpperBits = (highBits >>> 1) ^ sign;
|
||||
return Int64.fromBits(decodedLowerBits, decodedUpperBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a sint32 value from the binary bytes encoded as varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readSint32(bufferDecoder, start) {
|
||||
return readSint64(bufferDecoder, start).getLowBits();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a subarray of bytes representing a length delimited field.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!BufferDecoder}
|
||||
* @package
|
||||
*/
|
||||
function readDelimited(bufferDecoder, start) {
|
||||
const unsignedLength = bufferDecoder.getUnsignedVarint32At(start);
|
||||
return bufferDecoder.subBufferDecoder(bufferDecoder.cursor(), unsignedLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {string}
|
||||
* @package
|
||||
*/
|
||||
function readString(bufferDecoder, start) {
|
||||
return readDelimited(bufferDecoder, start).asString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a uint32 value from the binary bytes encoded as varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readUint32(bufferDecoder, start) {
|
||||
return bufferDecoder.getUnsignedVarint32At(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a double value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readDouble(bufferDecoder, start) {
|
||||
return bufferDecoder.getFloat64(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a fixed int32 value from the binary bytes.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {number}
|
||||
* @package
|
||||
*/
|
||||
function readSfixed32(bufferDecoder, start) {
|
||||
return bufferDecoder.getInt32(start);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* REPEATED FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads a packed bool field, which consists of a length header and a list of
|
||||
* unsigned varints.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<boolean>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedBool(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readBool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed double field, which consists of a length header and a list of
|
||||
* fixed64.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedDouble(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readDouble);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed fixed32 field, which consists of a length header and a list of
|
||||
* fixed32.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedFixed32(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readFixed32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed float field, which consists of a length header and a list of
|
||||
* fixed64.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedFloat(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readFloat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed int32 field, which consists of a length header and a list of
|
||||
* varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedInt32(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readInt32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed int64 field, which consists of a length header and a list
|
||||
* of int64.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<!Int64>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedInt64(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readInt64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed sfixed32 field, which consists of a length header and a list
|
||||
* of sfixed32.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedSfixed32(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readSfixed32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed sfixed64 field, which consists of a length header and a list
|
||||
* of sfixed64.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<!Int64>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedSfixed64(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readSfixed64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed sint32 field, which consists of a length header and a list of
|
||||
* varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedSint32(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readSint32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed sint64 field, which consists of a length header and a list
|
||||
* of sint64.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<!Int64>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedSint64(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readSint64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a packed uint32 field, which consists of a length header and a list of
|
||||
* varint.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @return {!Array<number>}
|
||||
* @package
|
||||
*/
|
||||
function readPackedUint32(bufferDecoder, start) {
|
||||
return readPacked(bufferDecoder, start, readUint32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read packed values.
|
||||
* @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
|
||||
* @param {number} start Start of the data.
|
||||
* @param {function(!BufferDecoder, number):T} valueFunction
|
||||
* @return {!Array<T>}
|
||||
* @package
|
||||
* @template T
|
||||
*/
|
||||
function readPacked(bufferDecoder, start, valueFunction) {
|
||||
const /** !Array<T> */ result = [];
|
||||
const unsignedLength = bufferDecoder.getUnsignedVarint32At(start);
|
||||
const dataStart = bufferDecoder.cursor();
|
||||
while (bufferDecoder.cursor() < dataStart + unsignedLength) {
|
||||
checkState(bufferDecoder.cursor() > 0);
|
||||
result.push(valueFunction(bufferDecoder, bufferDecoder.cursor()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
exports = {
|
||||
readBool,
|
||||
readBytes,
|
||||
readDelimited,
|
||||
readDouble,
|
||||
readFixed32,
|
||||
readFloat,
|
||||
readInt32,
|
||||
readInt64,
|
||||
readSint32,
|
||||
readSint64,
|
||||
readSfixed32,
|
||||
readSfixed64,
|
||||
readString,
|
||||
readUint32,
|
||||
readPackedBool,
|
||||
readPackedDouble,
|
||||
readPackedFixed32,
|
||||
readPackedFloat,
|
||||
readPackedInt32,
|
||||
readPackedInt64,
|
||||
readPackedSfixed32,
|
||||
readPackedSfixed64,
|
||||
readPackedSint32,
|
||||
readPackedSint64,
|
||||
readPackedUint32,
|
||||
};
|
425
deps/protobuf/js/experimental/runtime/kernel/reader_test.js
vendored
Normal file
425
deps/protobuf/js/experimental/runtime/kernel/reader_test.js
vendored
Normal file
@ -0,0 +1,425 @@
|
||||
/**
|
||||
* @fileoverview Tests for reader.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.ReaderTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
// Note to the reader:
|
||||
// Since the reader behavior changes with the checking level some of the
|
||||
// tests in this file have to know which checking level is enable to make
|
||||
// correct assertions.
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const reader = goog.require('protobuf.binary.reader');
|
||||
const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
const {encode} = goog.require('protobuf.binary.textencoding');
|
||||
const {getBoolPairs} = goog.require('protobuf.binary.boolTestPairs');
|
||||
const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs');
|
||||
const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs');
|
||||
const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs');
|
||||
const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs');
|
||||
const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs');
|
||||
const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs');
|
||||
const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs');
|
||||
const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs');
|
||||
const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs');
|
||||
const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs');
|
||||
const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs');
|
||||
const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs');
|
||||
const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs');
|
||||
const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs');
|
||||
const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs');
|
||||
const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs');
|
||||
const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs');
|
||||
const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs');
|
||||
const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs');
|
||||
const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs');
|
||||
const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs');
|
||||
|
||||
/******************************************************************************
|
||||
* Optional FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
describe('Read bool does', () => {
|
||||
for (const pair of getBoolPairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
if (pair.error && CHECK_CRITICAL_STATE) {
|
||||
expect(() => reader.readBool(pair.bufferDecoder, 0)).toThrow();
|
||||
} else {
|
||||
const d = reader.readBool(
|
||||
pair.bufferDecoder, pair.bufferDecoder.startIndex());
|
||||
expect(d).toEqual(pair.boolValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readBytes does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder();
|
||||
expect(() => reader.readBytes(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
it('read bytes by index', () => {
|
||||
const bufferDecoder = createBufferDecoder(3, 1, 2, 3);
|
||||
const byteString = reader.readBytes(bufferDecoder, 0);
|
||||
expect(ByteString.fromArrayBuffer(new Uint8Array([1, 2, 3]).buffer))
|
||||
.toEqual(byteString);
|
||||
});
|
||||
});
|
||||
|
||||
describe('readDouble does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder();
|
||||
expect(() => reader.readDouble(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getDoublePairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readDouble(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.doubleValue);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readFixed32 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder();
|
||||
expect(() => reader.readFixed32(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getFixed32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readFixed32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.intValue);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readFloat does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder();
|
||||
expect(() => reader.readFloat(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getFloatPairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readFloat(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(Math.fround(pair.floatValue));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readInt32 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readInt32(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getInt32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
if (pair.error && CHECK_CRITICAL_STATE) {
|
||||
expect(() => reader.readInt32(pair.bufferDecoder, 0)).toThrow();
|
||||
} else {
|
||||
const d = reader.readInt32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.intValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readSfixed32 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readSfixed32(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getSfixed32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readSfixed32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.intValue);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readSfixed64 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readSfixed64(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getSfixed64Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readSfixed64(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.longValue);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readSint32 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readSint32(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getSint32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
if (pair.error && CHECK_CRITICAL_STATE) {
|
||||
expect(() => reader.readSint32(pair.bufferDecoder, 0)).toThrow();
|
||||
} else {
|
||||
const d = reader.readSint32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.intValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readInt64 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readInt64(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getInt64Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
if (pair.error && CHECK_CRITICAL_STATE) {
|
||||
expect(() => reader.readInt64(pair.bufferDecoder, 0)).toThrow();
|
||||
} else {
|
||||
const d = reader.readInt64(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.longValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readSint64 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readSint64(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getSint64Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
if (pair.error && CHECK_CRITICAL_STATE) {
|
||||
expect(() => reader.readSint64(pair.bufferDecoder, 0)).toThrow();
|
||||
} else {
|
||||
const d = reader.readSint64(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.longValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readUint32 does', () => {
|
||||
it('throw exception if data is too short', () => {
|
||||
const bufferDecoder = createBufferDecoder(0x80);
|
||||
expect(() => reader.readUint32(bufferDecoder, 0)).toThrow();
|
||||
});
|
||||
|
||||
for (const pair of getUint32Pairs()) {
|
||||
if (!pair.skip_reader) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
if (pair.error && CHECK_CRITICAL_STATE) {
|
||||
expect(() => reader.readUint32(pair.bufferDecoder, 0)).toThrow();
|
||||
} else {
|
||||
const d = reader.readUint32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.intValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} s
|
||||
* @return {!Uint8Array}
|
||||
*/
|
||||
function encodeString(s) {
|
||||
if (typeof TextEncoder !== 'undefined') {
|
||||
const textEncoder = new TextEncoder('utf-8');
|
||||
return textEncoder.encode(s);
|
||||
} else {
|
||||
return encode(s);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {string} s */
|
||||
function expectEncodedStringToMatch(s) {
|
||||
const array = encodeString(s);
|
||||
const length = array.length;
|
||||
if (length > 127) {
|
||||
throw new Error('Test only works for strings shorter than 128');
|
||||
}
|
||||
const encodedArray = new Uint8Array(length + 1);
|
||||
encodedArray[0] = length;
|
||||
encodedArray.set(array, 1);
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(encodedArray.buffer);
|
||||
expect(reader.readString(bufferDecoder, 0)).toEqual(s);
|
||||
}
|
||||
|
||||
describe('readString does', () => {
|
||||
it('return empty string for zero length string', () => {
|
||||
const s = reader.readString(createBufferDecoder(0x00), 0);
|
||||
expect(s).toEqual('');
|
||||
});
|
||||
|
||||
it('decode random strings', () => {
|
||||
// 1 byte strings
|
||||
expectEncodedStringToMatch('hello');
|
||||
expectEncodedStringToMatch('HELLO1!');
|
||||
|
||||
// 2 byte String
|
||||
expectEncodedStringToMatch('©');
|
||||
|
||||
// 3 byte string
|
||||
expectEncodedStringToMatch('❄');
|
||||
|
||||
// 4 byte string
|
||||
expectEncodedStringToMatch('😁');
|
||||
});
|
||||
|
||||
it('decode 1 byte strings', () => {
|
||||
for (let i = 0; i < 0x80; i++) {
|
||||
const s = String.fromCharCode(i);
|
||||
expectEncodedStringToMatch(s);
|
||||
}
|
||||
});
|
||||
|
||||
it('decode 2 byte strings', () => {
|
||||
for (let i = 0xC0; i < 0x7FF; i++) {
|
||||
const s = String.fromCharCode(i);
|
||||
expectEncodedStringToMatch(s);
|
||||
}
|
||||
});
|
||||
|
||||
it('decode 3 byte strings', () => {
|
||||
for (let i = 0x7FF; i < 0x8FFF; i++) {
|
||||
const s = String.fromCharCode(i);
|
||||
expectEncodedStringToMatch(s);
|
||||
}
|
||||
});
|
||||
|
||||
it('throw exception on invalid bytes', () => {
|
||||
// This test will only succeed with the native TextDecoder since
|
||||
// our polyfill does not do any validation. IE10 and IE11 don't support
|
||||
// TextDecoder.
|
||||
// TODO: Remove this check once we no longer need to support IE
|
||||
if (typeof TextDecoder !== 'undefined') {
|
||||
expect(
|
||||
() => reader.readString(
|
||||
createBufferDecoder(0x01, /* invalid utf data point*/ 0xFF), 0))
|
||||
.toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
it('throw exception if data is too short', () => {
|
||||
const array = createBufferDecoder(0x02, '?'.charCodeAt(0));
|
||||
expect(() => reader.readString(array, 0)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
/******************************************************************************
|
||||
* REPEATED FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
describe('readPackedBool does', () => {
|
||||
for (const pair of getPackedBoolPairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedBool(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.boolValues);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedDouble does', () => {
|
||||
for (const pair of getPackedDoublePairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedDouble(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.doubleValues);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedFixed32 does', () => {
|
||||
for (const pair of getPackedFixed32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedFixed32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.fixed32Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedFloat does', () => {
|
||||
for (const pair of getPackedFloatPairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedFloat(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.floatValues);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedInt32 does', () => {
|
||||
for (const pair of getPackedInt32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedInt32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.int32Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedInt64 does', () => {
|
||||
for (const pair of getPackedInt64Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedInt64(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.int64Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedSfixed32 does', () => {
|
||||
for (const pair of getPackedSfixed32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedSfixed32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.sfixed32Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedSfixed64 does', () => {
|
||||
for (const pair of getPackedSfixed64Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedSfixed64(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.sfixed64Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedSint32 does', () => {
|
||||
for (const pair of getPackedSint32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedSint32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.sint32Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedSint64 does', () => {
|
||||
for (const pair of getPackedSint64Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedSint64(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.sint64Values);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('readPackedUint32 does', () => {
|
||||
for (const pair of getPackedUint32Pairs()) {
|
||||
it(`decode ${pair.name}`, () => {
|
||||
const d = reader.readPackedUint32(pair.bufferDecoder, 0);
|
||||
expect(d).toEqual(pair.uint32Values);
|
||||
});
|
||||
}
|
||||
});
|
46
deps/protobuf/js/experimental/runtime/kernel/sfixed32_test_pairs.js
vendored
Normal file
46
deps/protobuf/js/experimental/runtime/kernel/sfixed32_test_pairs.js
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @fileoverview Test data for sfixed32 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.sfixed32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of int values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, intValue: number, bufferDecoder:
|
||||
* !BufferDecoder}>}
|
||||
*/
|
||||
function getSfixed32Pairs() {
|
||||
const sfixed32Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
intValue: 0,
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'one',
|
||||
intValue: 1,
|
||||
bufferDecoder: createBufferDecoder(0x01, 0x00, 0x00, 0x00)
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
intValue: -1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF),
|
||||
},
|
||||
{
|
||||
name: 'max int 2^31 -1',
|
||||
intValue: Math.pow(2, 31) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0x7F)
|
||||
},
|
||||
{
|
||||
name: 'min int -2^31',
|
||||
intValue: -Math.pow(2, 31),
|
||||
bufferDecoder: createBufferDecoder(0x00, 0x00, 0x00, 0x80)
|
||||
},
|
||||
];
|
||||
return [...sfixed32Pairs];
|
||||
}
|
||||
|
||||
exports = {getSfixed32Pairs};
|
52
deps/protobuf/js/experimental/runtime/kernel/sfixed64_test_pairs.js
vendored
Normal file
52
deps/protobuf/js/experimental/runtime/kernel/sfixed64_test_pairs.js
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @fileoverview Test data for sfixed32 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.sfixed64TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of int values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, longValue: !Int64, bufferDecoder:
|
||||
* !BufferDecoder}>}
|
||||
*/
|
||||
function getSfixed64Pairs() {
|
||||
const sfixed64Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
longValue: Int64.fromInt(0),
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
|
||||
},
|
||||
{
|
||||
name: 'one',
|
||||
longValue: Int64.fromInt(1),
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
longValue: Int64.fromInt(-1),
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
|
||||
},
|
||||
{
|
||||
name: 'max int 2^63 -1',
|
||||
longValue: Int64.getMaxValue(),
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F)
|
||||
},
|
||||
{
|
||||
name: 'min int -2^63',
|
||||
longValue: Int64.getMinValue(),
|
||||
bufferDecoder:
|
||||
createBufferDecoder(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80)
|
||||
},
|
||||
];
|
||||
return [...sfixed64Pairs];
|
||||
}
|
||||
|
||||
exports = {getSfixed64Pairs};
|
57
deps/protobuf/js/experimental/runtime/kernel/sint32_test_pairs.js
vendored
Normal file
57
deps/protobuf/js/experimental/runtime/kernel/sint32_test_pairs.js
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @fileoverview Test data for int32 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.sint32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, intValue:number, bufferDecoder:
|
||||
* !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getSint32Pairs() {
|
||||
const sint32Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
intValue: 0,
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
intValue: 1,
|
||||
bufferDecoder: createBufferDecoder(0x02),
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
intValue: -1,
|
||||
bufferDecoder: createBufferDecoder(0x01),
|
||||
},
|
||||
{
|
||||
name: 'two',
|
||||
intValue: 2,
|
||||
bufferDecoder: createBufferDecoder(0x04),
|
||||
},
|
||||
{
|
||||
name: 'minus two',
|
||||
intValue: -2,
|
||||
bufferDecoder: createBufferDecoder(0x03),
|
||||
},
|
||||
{
|
||||
name: 'int 2^31 - 1',
|
||||
intValue: Math.pow(2, 31) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFE, 0xFF, 0xFF, 0xFF, 0x0F),
|
||||
|
||||
},
|
||||
{
|
||||
name: '-2^31',
|
||||
intValue: -Math.pow(2, 31),
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F),
|
||||
},
|
||||
];
|
||||
return [...sint32Pairs];
|
||||
}
|
||||
|
||||
exports = {getSint32Pairs};
|
60
deps/protobuf/js/experimental/runtime/kernel/sint64_test_pairs.js
vendored
Normal file
60
deps/protobuf/js/experimental/runtime/kernel/sint64_test_pairs.js
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @fileoverview Test data for sint64 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.sint64TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, longValue: !Int64, bufferDecoder:
|
||||
* !BufferDecoder, error: ?boolean, skip_writer: ?boolean}>}
|
||||
*/
|
||||
function getSint64Pairs() {
|
||||
const sint64Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
longValue: Int64.fromInt(0),
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
longValue: Int64.fromInt(1),
|
||||
bufferDecoder: createBufferDecoder(0x02),
|
||||
},
|
||||
{
|
||||
name: 'minus one',
|
||||
longValue: Int64.fromInt(-1),
|
||||
bufferDecoder: createBufferDecoder(0x01),
|
||||
},
|
||||
{
|
||||
name: 'two',
|
||||
longValue: Int64.fromInt(2),
|
||||
bufferDecoder: createBufferDecoder(0x04),
|
||||
},
|
||||
{
|
||||
name: 'minus two',
|
||||
longValue: Int64.fromInt(-2),
|
||||
bufferDecoder: createBufferDecoder(0x03),
|
||||
},
|
||||
{
|
||||
name: 'min value',
|
||||
longValue: Int64.getMinValue(),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
},
|
||||
|
||||
{
|
||||
name: 'max value',
|
||||
longValue: Int64.getMaxValue(),
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
},
|
||||
];
|
||||
return [...sint64Pairs];
|
||||
}
|
||||
|
||||
exports = {getSint64Pairs};
|
67
deps/protobuf/js/experimental/runtime/kernel/storage.js
vendored
Normal file
67
deps/protobuf/js/experimental/runtime/kernel/storage.js
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
goog.module('protobuf.runtime.Storage');
|
||||
|
||||
/**
|
||||
* Interface for getting and storing fields of a protobuf message.
|
||||
*
|
||||
* @interface
|
||||
* @package
|
||||
* @template FieldType
|
||||
*/
|
||||
class Storage {
|
||||
/**
|
||||
* Returns the pivot value.
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
getPivot() {}
|
||||
|
||||
/**
|
||||
* Sets a field in the specified field number.
|
||||
*
|
||||
* @param {number} fieldNumber
|
||||
* @param {!FieldType} field
|
||||
*/
|
||||
set(fieldNumber, field) {}
|
||||
|
||||
/**
|
||||
* Returns a field at the specified field number.
|
||||
*
|
||||
* @param {number} fieldNumber
|
||||
* @return {!FieldType|undefined}
|
||||
*/
|
||||
get(fieldNumber) {}
|
||||
|
||||
/**
|
||||
* Deletes a field from the specified field number.
|
||||
*
|
||||
* @param {number} fieldNumber
|
||||
*/
|
||||
delete(fieldNumber) {}
|
||||
|
||||
/**
|
||||
* Executes the provided function once for each field.
|
||||
*
|
||||
* @param {function(!FieldType, number): void} callback
|
||||
*/
|
||||
forEach(callback) {}
|
||||
|
||||
/**
|
||||
* Creates a shallow copy of the storage.
|
||||
*
|
||||
* @return {!Storage}
|
||||
*/
|
||||
shallowCopy() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* 85% of the proto fields have a field number <= 24:
|
||||
* https://plx.corp.google.com/scripts2/script_5d._f02af6_0000_23b1_a15f_001a1139dd02
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
// LINT.IfChange
|
||||
Storage.DEFAULT_PIVOT = 24;
|
||||
// LINT.ThenChange(//depot/google3/third_party/protobuf/javascript/runtime/kernel/binary_storage_test.js,
|
||||
// //depot/google3/net/proto2/contrib/js_proto/internal/kernel_message_generator.cc)
|
||||
|
||||
exports = Storage;
|
144
deps/protobuf/js/experimental/runtime/kernel/tag.js
vendored
Normal file
144
deps/protobuf/js/experimental/runtime/kernel/tag.js
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
goog.module('protobuf.binary.tag');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const WireType = goog.require('protobuf.binary.WireType');
|
||||
const {checkCriticalElementIndex, checkCriticalState} = goog.require('protobuf.internal.checks');
|
||||
|
||||
/**
|
||||
* Returns wire type stored in a tag.
|
||||
* Protos store the wire type as the first 3 bit of a tag.
|
||||
* @param {number} tag
|
||||
* @return {!WireType}
|
||||
*/
|
||||
function tagToWireType(tag) {
|
||||
return /** @type {!WireType} */ (tag & 0x07);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field number stored in a tag.
|
||||
* Protos store the field number in the upper 29 bits of a 32 bit number.
|
||||
* @param {number} tag
|
||||
* @return {number}
|
||||
*/
|
||||
function tagToFieldNumber(tag) {
|
||||
return tag >>> 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines wireType and fieldNumber into a tag.
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} fieldNumber
|
||||
* @return {number}
|
||||
*/
|
||||
function createTag(wireType, fieldNumber) {
|
||||
return (fieldNumber << 3 | wireType) >>> 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length, in bytes, of the field in the tag stream, less the tag
|
||||
* itself.
|
||||
* Note: This moves the cursor in the bufferDecoder.
|
||||
* @param {!BufferDecoder} bufferDecoder
|
||||
* @param {number} start
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} fieldNumber
|
||||
* @return {number}
|
||||
* @private
|
||||
*/
|
||||
function getTagLength(bufferDecoder, start, wireType, fieldNumber) {
|
||||
bufferDecoder.setCursor(start);
|
||||
skipField(bufferDecoder, wireType, fieldNumber);
|
||||
return bufferDecoder.cursor() - start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value
|
||||
* @return {number}
|
||||
*/
|
||||
function get32BitVarintLength(value) {
|
||||
if (value < 0) {
|
||||
return 5;
|
||||
}
|
||||
let size = 1;
|
||||
while (value >= 128) {
|
||||
size++;
|
||||
value >>>= 7;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips over a field.
|
||||
* Note: If the field is a start group the entire group will be skipped, placing
|
||||
* the cursor onto the next field.
|
||||
* @param {!BufferDecoder} bufferDecoder
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} fieldNumber
|
||||
*/
|
||||
function skipField(bufferDecoder, wireType, fieldNumber) {
|
||||
switch (wireType) {
|
||||
case WireType.VARINT:
|
||||
checkCriticalElementIndex(
|
||||
bufferDecoder.cursor(), bufferDecoder.endIndex());
|
||||
bufferDecoder.skipVarint();
|
||||
return;
|
||||
case WireType.FIXED64:
|
||||
bufferDecoder.skip(8);
|
||||
return;
|
||||
case WireType.DELIMITED:
|
||||
checkCriticalElementIndex(
|
||||
bufferDecoder.cursor(), bufferDecoder.endIndex());
|
||||
const length = bufferDecoder.getUnsignedVarint32();
|
||||
bufferDecoder.skip(length);
|
||||
return;
|
||||
case WireType.START_GROUP:
|
||||
const foundGroup = skipGroup_(bufferDecoder, fieldNumber);
|
||||
checkCriticalState(foundGroup, 'No end group found.');
|
||||
return;
|
||||
case WireType.FIXED32:
|
||||
bufferDecoder.skip(4);
|
||||
return;
|
||||
default:
|
||||
throw new Error(`Unexpected wire type: ${wireType}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips over fields until it finds the end of a given group consuming the stop
|
||||
* group tag.
|
||||
* @param {!BufferDecoder} bufferDecoder
|
||||
* @param {number} groupFieldNumber
|
||||
* @return {boolean} Whether the end group tag was found.
|
||||
* @private
|
||||
*/
|
||||
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 (wireType === WireType.END_GROUP) {
|
||||
checkCriticalState(
|
||||
groupFieldNumber === fieldNumber,
|
||||
`Expected stop group for fieldnumber ${groupFieldNumber} not found.`);
|
||||
return true;
|
||||
} else {
|
||||
skipField(bufferDecoder, wireType, fieldNumber);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
exports = {
|
||||
createTag,
|
||||
get32BitVarintLength,
|
||||
getTagLength,
|
||||
skipField,
|
||||
tagToWireType,
|
||||
tagToFieldNumber,
|
||||
};
|
221
deps/protobuf/js/experimental/runtime/kernel/tag_test.js
vendored
Normal file
221
deps/protobuf/js/experimental/runtime/kernel/tag_test.js
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
/**
|
||||
* @fileoverview Tests for tag.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.TagTests');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const WireType = goog.require('protobuf.binary.WireType');
|
||||
const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
|
||||
const {createTag, get32BitVarintLength, skipField, tagToFieldNumber, tagToWireType} = goog.require('protobuf.binary.tag');
|
||||
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
/**
|
||||
* @param {...number} bytes
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
function createArrayBuffer(...bytes) {
|
||||
return new Uint8Array(bytes).buffer;
|
||||
}
|
||||
|
||||
describe('skipField', () => {
|
||||
it('skips varints', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
|
||||
skipField(bufferDecoder, WireType.VARINT, 1);
|
||||
expect(bufferDecoder.cursor()).toBe(2);
|
||||
});
|
||||
|
||||
it('throws for out of bounds varints', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
|
||||
bufferDecoder.setCursor(2);
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => skipField(bufferDecoder, WireType.VARINT, 1)).toThrowError();
|
||||
}
|
||||
});
|
||||
|
||||
it('skips fixed64', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
|
||||
skipField(bufferDecoder, WireType.FIXED64, 1);
|
||||
expect(bufferDecoder.cursor()).toBe(8);
|
||||
});
|
||||
|
||||
it('throws for fixed64 if length is too short', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => skipField(bufferDecoder, WireType.FIXED64, 1))
|
||||
.toThrowError();
|
||||
}
|
||||
});
|
||||
|
||||
it('skips fixed32', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x80, 0x00, 0x00, 0x00));
|
||||
skipField(bufferDecoder, WireType.FIXED32, 1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
|
||||
it('throws for fixed32 if length is too short', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x80, 0x00));
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => skipField(bufferDecoder, WireType.FIXED32, 1))
|
||||
.toThrowError();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it('skips length delimited', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x03, 0x00, 0x00, 0x00));
|
||||
skipField(bufferDecoder, WireType.DELIMITED, 1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
|
||||
it('throws for length delimited if length is too short', () => {
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x03, 0x00, 0x00));
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => skipField(bufferDecoder, WireType.DELIMITED, 1))
|
||||
.toThrowError();
|
||||
}
|
||||
});
|
||||
|
||||
it('skips groups', () => {
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(
|
||||
createArrayBuffer(0x0B, 0x08, 0x01, 0x0C));
|
||||
bufferDecoder.setCursor(1);
|
||||
skipField(bufferDecoder, WireType.START_GROUP, 1);
|
||||
expect(bufferDecoder.cursor()).toBe(4);
|
||||
});
|
||||
|
||||
it('skips group in group', () => {
|
||||
const buffer = createArrayBuffer(
|
||||
0x0B, // start outer
|
||||
0x10, 0x01, // field: 2, value: 1
|
||||
0x0B, // start inner group
|
||||
0x10, 0x01, // payload inner group
|
||||
0x0C, // stop inner group
|
||||
0x0C // end outer
|
||||
);
|
||||
const bufferDecoder = BufferDecoder.fromArrayBuffer(buffer);
|
||||
bufferDecoder.setCursor(1);
|
||||
skipField(bufferDecoder, WireType.START_GROUP, 1);
|
||||
expect(bufferDecoder.cursor()).toBe(8);
|
||||
});
|
||||
|
||||
it('throws for group if length is too short', () => {
|
||||
// no closing group
|
||||
const bufferDecoder =
|
||||
BufferDecoder.fromArrayBuffer(createArrayBuffer(0x0B, 0x00, 0x00));
|
||||
if (CHECK_CRITICAL_STATE) {
|
||||
expect(() => skipField(bufferDecoder, WireType.START_GROUP, 1))
|
||||
.toThrowError();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('tagToWireType', () => {
|
||||
it('decodes numbers ', () => {
|
||||
// simple numbers
|
||||
expect(tagToWireType(0x00)).toBe(WireType.VARINT);
|
||||
expect(tagToWireType(0x01)).toBe(WireType.FIXED64);
|
||||
expect(tagToWireType(0x02)).toBe(WireType.DELIMITED);
|
||||
expect(tagToWireType(0x03)).toBe(WireType.START_GROUP);
|
||||
expect(tagToWireType(0x04)).toBe(WireType.END_GROUP);
|
||||
expect(tagToWireType(0x05)).toBe(WireType.FIXED32);
|
||||
|
||||
// upper bits should not matter
|
||||
expect(tagToWireType(0x08)).toBe(WireType.VARINT);
|
||||
expect(tagToWireType(0x09)).toBe(WireType.FIXED64);
|
||||
expect(tagToWireType(0x0A)).toBe(WireType.DELIMITED);
|
||||
expect(tagToWireType(0x0B)).toBe(WireType.START_GROUP);
|
||||
expect(tagToWireType(0x0C)).toBe(WireType.END_GROUP);
|
||||
expect(tagToWireType(0x0D)).toBe(WireType.FIXED32);
|
||||
|
||||
// upper bits should not matter
|
||||
expect(tagToWireType(0xF8)).toBe(WireType.VARINT);
|
||||
expect(tagToWireType(0xF9)).toBe(WireType.FIXED64);
|
||||
expect(tagToWireType(0xFA)).toBe(WireType.DELIMITED);
|
||||
expect(tagToWireType(0xFB)).toBe(WireType.START_GROUP);
|
||||
expect(tagToWireType(0xFC)).toBe(WireType.END_GROUP);
|
||||
expect(tagToWireType(0xFD)).toBe(WireType.FIXED32);
|
||||
|
||||
// negative numbers work
|
||||
expect(tagToWireType(-8)).toBe(WireType.VARINT);
|
||||
expect(tagToWireType(-7)).toBe(WireType.FIXED64);
|
||||
expect(tagToWireType(-6)).toBe(WireType.DELIMITED);
|
||||
expect(tagToWireType(-5)).toBe(WireType.START_GROUP);
|
||||
expect(tagToWireType(-4)).toBe(WireType.END_GROUP);
|
||||
expect(tagToWireType(-3)).toBe(WireType.FIXED32);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tagToFieldNumber', () => {
|
||||
it('returns fieldNumber', () => {
|
||||
expect(tagToFieldNumber(0x08)).toBe(1);
|
||||
expect(tagToFieldNumber(0x09)).toBe(1);
|
||||
expect(tagToFieldNumber(0x10)).toBe(2);
|
||||
expect(tagToFieldNumber(0x12)).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createTag', () => {
|
||||
it('combines fieldNumber and wireType', () => {
|
||||
expect(createTag(WireType.VARINT, 1)).toBe(0x08);
|
||||
expect(createTag(WireType.FIXED64, 1)).toBe(0x09);
|
||||
expect(createTag(WireType.DELIMITED, 1)).toBe(0x0A);
|
||||
expect(createTag(WireType.START_GROUP, 1)).toBe(0x0B);
|
||||
expect(createTag(WireType.END_GROUP, 1)).toBe(0x0C);
|
||||
expect(createTag(WireType.FIXED32, 1)).toBe(0x0D);
|
||||
|
||||
expect(createTag(WireType.VARINT, 2)).toBe(0x10);
|
||||
expect(createTag(WireType.FIXED64, 2)).toBe(0x11);
|
||||
expect(createTag(WireType.DELIMITED, 2)).toBe(0x12);
|
||||
expect(createTag(WireType.START_GROUP, 2)).toBe(0x13);
|
||||
expect(createTag(WireType.END_GROUP, 2)).toBe(0x14);
|
||||
expect(createTag(WireType.FIXED32, 2)).toBe(0x15);
|
||||
|
||||
expect(createTag(WireType.VARINT, 0x1FFFFFFF)).toBe(0xFFFFFFF8 >>> 0);
|
||||
expect(createTag(WireType.FIXED64, 0x1FFFFFFF)).toBe(0xFFFFFFF9 >>> 0);
|
||||
expect(createTag(WireType.DELIMITED, 0x1FFFFFFF)).toBe(0xFFFFFFFA >>> 0);
|
||||
expect(createTag(WireType.START_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFB >>> 0);
|
||||
expect(createTag(WireType.END_GROUP, 0x1FFFFFFF)).toBe(0xFFFFFFFC >>> 0);
|
||||
expect(createTag(WireType.FIXED32, 0x1FFFFFFF)).toBe(0xFFFFFFFD >>> 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('get32BitVarintLength', () => {
|
||||
it('length of tag', () => {
|
||||
expect(get32BitVarintLength(0)).toBe(1);
|
||||
expect(get32BitVarintLength(1)).toBe(1);
|
||||
expect(get32BitVarintLength(1)).toBe(1);
|
||||
|
||||
expect(get32BitVarintLength(Math.pow(2, 7) - 1)).toBe(1);
|
||||
expect(get32BitVarintLength(Math.pow(2, 7))).toBe(2);
|
||||
|
||||
expect(get32BitVarintLength(Math.pow(2, 14) - 1)).toBe(2);
|
||||
expect(get32BitVarintLength(Math.pow(2, 14))).toBe(3);
|
||||
|
||||
expect(get32BitVarintLength(Math.pow(2, 21) - 1)).toBe(3);
|
||||
expect(get32BitVarintLength(Math.pow(2, 21))).toBe(4);
|
||||
|
||||
expect(get32BitVarintLength(Math.pow(2, 28) - 1)).toBe(4);
|
||||
expect(get32BitVarintLength(Math.pow(2, 28))).toBe(5);
|
||||
|
||||
expect(get32BitVarintLength(Math.pow(2, 31) - 1)).toBe(5);
|
||||
|
||||
expect(get32BitVarintLength(-1)).toBe(5);
|
||||
expect(get32BitVarintLength(-Math.pow(2, 31))).toBe(5);
|
||||
|
||||
expect(get32BitVarintLength(createTag(WireType.VARINT, 0x1fffffff)))
|
||||
.toBe(5);
|
||||
expect(get32BitVarintLength(createTag(WireType.FIXED32, 0x1fffffff)))
|
||||
.toBe(5);
|
||||
});
|
||||
});
|
116
deps/protobuf/js/experimental/runtime/kernel/textencoding.js
vendored
Normal file
116
deps/protobuf/js/experimental/runtime/kernel/textencoding.js
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @fileoverview A UTF8 decoder.
|
||||
*/
|
||||
goog.module('protobuf.binary.textencoding');
|
||||
|
||||
const {checkElementIndex} = goog.require('protobuf.internal.checks');
|
||||
|
||||
/**
|
||||
* Combines an array of codePoints into a string.
|
||||
* @param {!Array<number>} codePoints
|
||||
* @return {string}
|
||||
*/
|
||||
function codePointsToString(codePoints) {
|
||||
// Performance: http://jsperf.com/string-fromcharcode-test/13
|
||||
let s = '', i = 0;
|
||||
const length = codePoints.length;
|
||||
const BATCH_SIZE = 10000;
|
||||
while (i < length) {
|
||||
const end = Math.min(i + BATCH_SIZE, length);
|
||||
s += String.fromCharCode.apply(null, codePoints.slice(i, end));
|
||||
i = end;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes raw bytes into a string.
|
||||
* Supports codepoints from U+0000 up to U+10FFFF.
|
||||
* (http://en.wikipedia.org/wiki/UTF-8).
|
||||
* @param {!DataView} bytes
|
||||
* @return {string}
|
||||
*/
|
||||
function decode(bytes) {
|
||||
let cursor = 0;
|
||||
const codePoints = [];
|
||||
|
||||
while (cursor < bytes.byteLength) {
|
||||
const c = bytes.getUint8(cursor++);
|
||||
if (c < 0x80) { // Regular 7-bit ASCII.
|
||||
codePoints.push(c);
|
||||
} else if (c < 0xC0) {
|
||||
// UTF-8 continuation mark. We are out of sync. This
|
||||
// might happen if we attempted to read a character
|
||||
// with more than four bytes.
|
||||
continue;
|
||||
} else if (c < 0xE0) { // UTF-8 with two bytes.
|
||||
checkElementIndex(cursor, bytes.byteLength);
|
||||
const c2 = bytes.getUint8(cursor++);
|
||||
codePoints.push(((c & 0x1F) << 6) | (c2 & 0x3F));
|
||||
} else if (c < 0xF0) { // UTF-8 with three bytes.
|
||||
checkElementIndex(cursor + 1, bytes.byteLength);
|
||||
const c2 = bytes.getUint8(cursor++);
|
||||
const c3 = bytes.getUint8(cursor++);
|
||||
codePoints.push(((c & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
|
||||
} else if (c < 0xF8) { // UTF-8 with 4 bytes.
|
||||
checkElementIndex(cursor + 2, bytes.byteLength);
|
||||
const c2 = bytes.getUint8(cursor++);
|
||||
const c3 = bytes.getUint8(cursor++);
|
||||
const c4 = bytes.getUint8(cursor++);
|
||||
// Characters written on 4 bytes have 21 bits for a codepoint.
|
||||
// We can't fit that on 16bit characters, so we use surrogates.
|
||||
let codepoint = ((c & 0x07) << 18) | ((c2 & 0x3F) << 12) |
|
||||
((c3 & 0x3F) << 6) | (c4 & 0x3F);
|
||||
// Surrogates formula from wikipedia.
|
||||
// 1. Subtract 0x10000 from codepoint
|
||||
codepoint -= 0x10000;
|
||||
// 2. Split this into the high 10-bit value and the low 10-bit value
|
||||
// 3. Add 0xD800 to the high value to form the high surrogate
|
||||
// 4. Add 0xDC00 to the low value to form the low surrogate:
|
||||
const low = (codepoint & 0x3FF) + 0xDC00;
|
||||
const high = ((codepoint >> 10) & 0x3FF) + 0xD800;
|
||||
codePoints.push(high, low);
|
||||
}
|
||||
}
|
||||
return codePointsToString(codePoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a UTF16 JavaScript string to the buffer encoded as UTF8.
|
||||
* @param {string} value The string to write.
|
||||
* @return {!Uint8Array} An array containing the encoded bytes.
|
||||
*/
|
||||
function encode(value) {
|
||||
const buffer = [];
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const c1 = value.charCodeAt(i);
|
||||
|
||||
if (c1 < 0x80) {
|
||||
buffer.push(c1);
|
||||
} else if (c1 < 0x800) {
|
||||
buffer.push((c1 >> 6) | 0xC0);
|
||||
buffer.push((c1 & 0x3F) | 0x80);
|
||||
} else if (c1 < 0xD800 || c1 >= 0xE000) {
|
||||
buffer.push((c1 >> 12) | 0xE0);
|
||||
buffer.push(((c1 >> 6) & 0x3F) | 0x80);
|
||||
buffer.push((c1 & 0x3F) | 0x80);
|
||||
} else {
|
||||
// surrogate pair
|
||||
i++;
|
||||
checkElementIndex(i, value.length);
|
||||
const c2 = value.charCodeAt(i);
|
||||
const paired = 0x10000 + (((c1 & 0x3FF) << 10) | (c2 & 0x3FF));
|
||||
buffer.push((paired >> 18) | 0xF0);
|
||||
buffer.push(((paired >> 12) & 0x3F) | 0x80);
|
||||
buffer.push(((paired >> 6) & 0x3F) | 0x80);
|
||||
buffer.push((paired & 0x3F) | 0x80);
|
||||
}
|
||||
}
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
|
||||
exports = {
|
||||
decode,
|
||||
encode,
|
||||
};
|
113
deps/protobuf/js/experimental/runtime/kernel/textencoding_test.js
vendored
Normal file
113
deps/protobuf/js/experimental/runtime/kernel/textencoding_test.js
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @fileoverview Tests for textdecoder.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.TextDecoderTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
const {decode, encode} = goog.require('protobuf.binary.textencoding');
|
||||
|
||||
describe('Decode does', () => {
|
||||
it('return empty string for empty array', () => {
|
||||
expect(decode(new DataView(new ArrayBuffer(0)))).toEqual('');
|
||||
});
|
||||
|
||||
it('throw on null being passed', () => {
|
||||
expect(() => decode(/** @type {!DataView} */ (/** @type {*} */ (null))))
|
||||
.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Encode does', () => {
|
||||
it('return empty array for empty string', () => {
|
||||
expect(encode('')).toEqual(new Uint8Array(0));
|
||||
});
|
||||
|
||||
it('throw on null being passed', () => {
|
||||
expect(() => encode(/** @type {string} */ (/** @type {*} */ (null))))
|
||||
.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
/** @const {!TextEncoder} */
|
||||
const textEncoder = new TextEncoder('utf-8');
|
||||
|
||||
/**
|
||||
* A Pair of string and Uint8Array representing the same data.
|
||||
* Each pair has the string value and its utf-8 bytes.
|
||||
*/
|
||||
class Pair {
|
||||
/**
|
||||
* Constructs a pair from a given string.
|
||||
* @param {string} s
|
||||
* @return {!Pair}
|
||||
*/
|
||||
static fromString(s) {
|
||||
return new Pair(s, textEncoder.encode(s).buffer);
|
||||
}
|
||||
/**
|
||||
* Constructs a pair from a given charCode.
|
||||
* @param {number} charCode
|
||||
* @return {!Pair}
|
||||
*/
|
||||
static fromCharCode(charCode) {
|
||||
return Pair.fromString(String.fromCharCode(charCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} stringValue
|
||||
* @param {!ArrayBuffer} bytes
|
||||
* @private
|
||||
*/
|
||||
constructor(stringValue, bytes) {
|
||||
/** @const @private {string} */
|
||||
this.stringValue_ = stringValue;
|
||||
/** @const @private {!ArrayBuffer} */
|
||||
this.bytes_ = bytes;
|
||||
}
|
||||
|
||||
/** Ensures that a given pair encodes and decodes round trip*/
|
||||
expectPairToMatch() {
|
||||
expect(decode(new DataView(this.bytes_))).toEqual(this.stringValue_);
|
||||
expect(encode(this.stringValue_)).toEqual(new Uint8Array(this.bytes_));
|
||||
}
|
||||
}
|
||||
|
||||
describe('textencoding does', () => {
|
||||
it('works for empty string', () => {
|
||||
Pair.fromString('').expectPairToMatch();
|
||||
});
|
||||
|
||||
it('decode and encode random strings', () => {
|
||||
// 1 byte strings
|
||||
Pair.fromString('hello').expectPairToMatch();
|
||||
Pair.fromString('HELLO1!');
|
||||
|
||||
// 2 byte String
|
||||
Pair.fromString('©').expectPairToMatch();
|
||||
|
||||
// 3 byte string
|
||||
Pair.fromString('❄').expectPairToMatch();
|
||||
|
||||
// 4 byte string
|
||||
Pair.fromString('😁').expectPairToMatch();
|
||||
});
|
||||
|
||||
it('decode and encode 1 byte strings', () => {
|
||||
for (let i = 0; i < 0x80; i++) {
|
||||
Pair.fromCharCode(i).expectPairToMatch();
|
||||
}
|
||||
});
|
||||
|
||||
it('decode and encode 2 byte strings', () => {
|
||||
for (let i = 0xC0; i < 0x7FF; i++) {
|
||||
Pair.fromCharCode(i).expectPairToMatch();
|
||||
}
|
||||
});
|
||||
|
||||
it('decode and encode 3 byte strings', () => {
|
||||
for (let i = 0x7FF; i < 0x8FFF; i++) {
|
||||
Pair.fromCharCode(i).expectPairToMatch();
|
||||
}
|
||||
});
|
||||
});
|
116
deps/protobuf/js/experimental/runtime/kernel/typed_arrays.js
vendored
Normal file
116
deps/protobuf/js/experimental/runtime/kernel/typed_arrays.js
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @fileoverview Helper methods for typed arrays.
|
||||
*/
|
||||
goog.module('protobuf.binary.typedArrays');
|
||||
|
||||
const {assert} = goog.require('goog.asserts');
|
||||
|
||||
/**
|
||||
* @param {!ArrayBuffer} buffer1
|
||||
* @param {!ArrayBuffer} buffer2
|
||||
* @return {boolean}
|
||||
*/
|
||||
function arrayBufferEqual(buffer1, buffer2) {
|
||||
if (!buffer1 || !buffer2) {
|
||||
throw new Error('Buffer shouldn\'t be empty');
|
||||
}
|
||||
|
||||
const array1 = new Uint8Array(buffer1);
|
||||
const array2 = new Uint8Array(buffer2);
|
||||
|
||||
return uint8ArrayEqual(array1, array2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Uint8Array} array1
|
||||
* @param {!Uint8Array} array2
|
||||
* @return {boolean}
|
||||
*/
|
||||
function uint8ArrayEqual(array1, array2) {
|
||||
if (array1 === array2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (array1.byteLength !== array2.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < array1.byteLength; i++) {
|
||||
if (array1[i] !== array2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayBuffer.prototype.slice, but fallback to manual copy if missing.
|
||||
* @param {!ArrayBuffer} buffer
|
||||
* @param {number} start
|
||||
* @param {number=} end
|
||||
* @return {!ArrayBuffer} New array buffer with given the contents of `buffer`.
|
||||
*/
|
||||
function arrayBufferSlice(buffer, start, end = undefined) {
|
||||
// The fallback isn't fully compatible with ArrayBuffer.slice, enforce
|
||||
// strict requirements on start/end.
|
||||
// Spec:
|
||||
// https://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer.prototype.slice
|
||||
assert(start >= 0);
|
||||
assert(end === undefined || (end >= 0 && end <= buffer.byteLength));
|
||||
assert((end === undefined ? buffer.byteLength : end) >= start);
|
||||
if (buffer.slice) {
|
||||
const slicedBuffer = buffer.slice(start, end);
|
||||
// The ArrayBuffer.prototype.slice function was flawed before iOS 12.2. This
|
||||
// causes 0-length results when passing undefined or a number greater
|
||||
// than 32 bits for the optional end value. In these cases, we fall back to
|
||||
// using our own slice implementation.
|
||||
// More details: https://bugs.webkit.org/show_bug.cgi?id=185127
|
||||
if (slicedBuffer.byteLength !== 0 || (start === end)) {
|
||||
return slicedBuffer;
|
||||
}
|
||||
}
|
||||
const realEnd = end == null ? buffer.byteLength : end;
|
||||
const length = realEnd - start;
|
||||
assert(length >= 0);
|
||||
const view = new Uint8Array(buffer, start, length);
|
||||
// A TypedArray constructed from another Typed array copies the data.
|
||||
const clone = new Uint8Array(view);
|
||||
|
||||
return clone.buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Uint8Array with the size and contents of the given
|
||||
* ArrayBufferView. ArrayBufferView is an interface implemented by DataView,
|
||||
* Uint8Array and all typed arrays.
|
||||
* @param {!ArrayBufferView} view
|
||||
* @return {!Uint8Array}
|
||||
*/
|
||||
function cloneArrayBufferView(view) {
|
||||
return new Uint8Array(arrayBufferSlice(
|
||||
view.buffer, view.byteOffset, view.byteOffset + view.byteLength));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a 32 bit number for the corresponding Uint8Array.
|
||||
* @param {!Uint8Array} array
|
||||
* @return {number}
|
||||
*/
|
||||
function hashUint8Array(array) {
|
||||
const prime = 31;
|
||||
let result = 17;
|
||||
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
// '| 0' ensures signed 32 bits
|
||||
result = (result * prime + array[i]) | 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
exports = {
|
||||
arrayBufferEqual,
|
||||
uint8ArrayEqual,
|
||||
arrayBufferSlice,
|
||||
cloneArrayBufferView,
|
||||
hashUint8Array,
|
||||
};
|
191
deps/protobuf/js/experimental/runtime/kernel/typed_arrays_test.js
vendored
Normal file
191
deps/protobuf/js/experimental/runtime/kernel/typed_arrays_test.js
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @fileoverview Tests for typed_arrays.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.typedArraysTest');
|
||||
|
||||
const {arrayBufferEqual, arrayBufferSlice, cloneArrayBufferView, hashUint8Array, uint8ArrayEqual} = goog.require('protobuf.binary.typedArrays');
|
||||
|
||||
describe('arrayBufferEqual', () => {
|
||||
it('returns true for empty buffers', () => {
|
||||
const buffer1 = new ArrayBuffer(0);
|
||||
const buffer2 = new ArrayBuffer(0);
|
||||
expect(arrayBufferEqual(buffer1, buffer2)).toBe(true);
|
||||
});
|
||||
|
||||
it('throws for first null buffers', () => {
|
||||
const buffer = new ArrayBuffer(0);
|
||||
expect(
|
||||
() => arrayBufferEqual(
|
||||
/** @type {!ArrayBuffer} */ (/** @type {*} */ (null)), buffer))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it('throws for second null buffers', () => {
|
||||
const buffer = new ArrayBuffer(0);
|
||||
expect(
|
||||
() => arrayBufferEqual(
|
||||
buffer, /** @type {!ArrayBuffer} */ (/** @type {*} */ (null))))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it('returns true for arrays with same values', () => {
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
const array2 = new Uint8Array(4);
|
||||
array2[0] = 1;
|
||||
expect(arrayBufferEqual(array1.buffer, array2.buffer)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for arrays with different values', () => {
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
const array2 = new Uint8Array(4);
|
||||
array2[0] = 2;
|
||||
expect(arrayBufferEqual(array1.buffer, array2.buffer)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true same instance', () => {
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
expect(arrayBufferEqual(array1.buffer, array1.buffer)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('uint8ArrayEqual', () => {
|
||||
it('returns true for empty arrays', () => {
|
||||
const array1 = new Uint8Array(0);
|
||||
const array2 = new Uint8Array(0);
|
||||
expect(uint8ArrayEqual(array1, array2)).toBe(true);
|
||||
});
|
||||
|
||||
it('throws for first Uint8Array array', () => {
|
||||
const array = new Uint8Array(0);
|
||||
expect(
|
||||
() => uint8ArrayEqual(
|
||||
/** @type {!Uint8Array} */ (/** @type {*} */ (null)), array))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it('throws for second null array', () => {
|
||||
const array = new Uint8Array(0);
|
||||
expect(
|
||||
() => uint8ArrayEqual(
|
||||
array, /** @type {!Uint8Array} */ (/** @type {*} */ (null))))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it('returns true for arrays with same values', () => {
|
||||
const buffer1 = new Uint8Array([0, 1, 2, 3]).buffer;
|
||||
const buffer2 = new Uint8Array([1, 2, 3, 4]).buffer;
|
||||
const array1 = new Uint8Array(buffer1, 1, 3);
|
||||
const array2 = new Uint8Array(buffer2, 0, 3);
|
||||
expect(uint8ArrayEqual(array1, array2)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for arrays with different values', () => {
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
const array2 = new Uint8Array(4);
|
||||
array2[0] = 2;
|
||||
expect(uint8ArrayEqual(array1, array2)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true same instance', () => {
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
expect(uint8ArrayEqual(array1, array1)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('arrayBufferSlice', () => {
|
||||
it('Returns a new instance.', () => {
|
||||
const buffer1 = new ArrayBuffer(0);
|
||||
const buffer2 = arrayBufferSlice(buffer1, 0);
|
||||
expect(buffer2).not.toBe(buffer1);
|
||||
expect(arrayBufferEqual(buffer1, buffer2)).toBe(true);
|
||||
});
|
||||
|
||||
it('Copies data with positive start/end.', () => {
|
||||
const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer;
|
||||
expect(buffer1.byteLength).toEqual(10);
|
||||
|
||||
const buffer2 = arrayBufferSlice(buffer1, 2, 6);
|
||||
expect(buffer2.byteLength).toEqual(4);
|
||||
expect(buffer2).not.toBe(buffer1);
|
||||
const expected = new Uint8Array([2, 3, 4, 5]).buffer;
|
||||
expect(arrayBufferEqual(expected, buffer2)).toBe(true);
|
||||
});
|
||||
|
||||
it('Copies all data without end.', () => {
|
||||
const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer;
|
||||
expect(buffer1.byteLength).toEqual(10);
|
||||
|
||||
const buffer2 = arrayBufferSlice(buffer1, 0);
|
||||
expect(buffer2.byteLength).toEqual(10);
|
||||
expect(arrayBufferEqual(buffer1, buffer2)).toBe(true);
|
||||
});
|
||||
|
||||
if (goog.DEBUG) {
|
||||
it('Fails with negative end.', () => {
|
||||
const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer;
|
||||
expect(() => void arrayBufferSlice(buffer1, 2, -1)).toThrow();
|
||||
});
|
||||
|
||||
it('Fails with negative start.', () => {
|
||||
const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer;
|
||||
expect(() => void arrayBufferSlice(buffer1, 2, -1)).toThrow();
|
||||
});
|
||||
|
||||
it('Fails when start > end.', () => {
|
||||
const buffer1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).buffer;
|
||||
expect(() => void arrayBufferSlice(buffer1, 2, 1)).toThrow();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('cloneArrayBufferView', () => {
|
||||
it('Returns a new instance.', () => {
|
||||
const array1 = new Uint8Array(0);
|
||||
const array2 = cloneArrayBufferView(new Uint8Array(array1));
|
||||
expect(array2).not.toBe(array1);
|
||||
expect(uint8ArrayEqual(array1, array2)).toBe(true);
|
||||
});
|
||||
|
||||
it('Returns an array of the exact size.', () => {
|
||||
const array1 =
|
||||
new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]).subarray(2, 5);
|
||||
expect(array1.length).toEqual(3);
|
||||
expect(array1.buffer.byteLength).toEqual(10);
|
||||
const array2 = cloneArrayBufferView(array1);
|
||||
expect(array2.byteLength).toEqual(3);
|
||||
expect(array2).toEqual(new Uint8Array([2, 3, 4]));
|
||||
});
|
||||
});
|
||||
|
||||
describe('hashUint8Array', () => {
|
||||
it('returns same hashcode for empty Uint8Arrays', () => {
|
||||
const array1 = new Uint8Array(0);
|
||||
const array2 = new Uint8Array(0);
|
||||
expect(hashUint8Array(array1)).toBe(hashUint8Array(array2));
|
||||
});
|
||||
|
||||
it('returns same hashcode for Uint8Arrays with same values', () => {
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
const array2 = new Uint8Array(4);
|
||||
array2[0] = 1;
|
||||
expect(hashUint8Array(array1)).toBe(hashUint8Array(array2));
|
||||
});
|
||||
|
||||
it('returns different hashcode for Uint8Arrays with different values', () => {
|
||||
// This test might fail in the future if the hashing algorithm is updated
|
||||
// and we end up with a collision here.
|
||||
// We still need this test to make sure that we are not just returning
|
||||
// the same number for all buffers.
|
||||
const array1 = new Uint8Array(4);
|
||||
array1[0] = 1;
|
||||
const array2 = new Uint8Array(4);
|
||||
array2[0] = 2;
|
||||
expect(hashUint8Array(array1)).not.toBe(hashUint8Array(array2));
|
||||
});
|
||||
});
|
68
deps/protobuf/js/experimental/runtime/kernel/uint32_test_pairs.js
vendored
Normal file
68
deps/protobuf/js/experimental/runtime/kernel/uint32_test_pairs.js
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @fileoverview Test data for int32 encoding and decoding.
|
||||
*/
|
||||
goog.module('protobuf.binary.uint32TestPairs');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
|
||||
|
||||
/**
|
||||
* An array of Pairs of float values and their bit representation.
|
||||
* This is used to test encoding and decoding from/to the protobuf wire format.
|
||||
* @return {!Array<{name: string, intValue:number, bufferDecoder:
|
||||
* !BufferDecoder, error: (boolean|undefined),
|
||||
* skip_reader: (boolean|undefined), skip_writer: (boolean|undefined)}>}
|
||||
*/
|
||||
function getUint32Pairs() {
|
||||
const uint32Pairs = [
|
||||
{
|
||||
name: 'zero',
|
||||
intValue: 0,
|
||||
bufferDecoder: createBufferDecoder(0x00),
|
||||
},
|
||||
{
|
||||
name: 'one ',
|
||||
intValue: 1,
|
||||
bufferDecoder: createBufferDecoder(0x01),
|
||||
},
|
||||
{
|
||||
name: 'max signed int 2^31 - 1',
|
||||
intValue: Math.pow(2, 31) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x07),
|
||||
},
|
||||
{
|
||||
name: 'max unsigned int 2^32 - 1',
|
||||
intValue: Math.pow(2, 32) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F),
|
||||
},
|
||||
{
|
||||
name: 'negative one',
|
||||
intValue: -1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x0F),
|
||||
skip_reader: true,
|
||||
},
|
||||
{
|
||||
name: 'truncates more than 32 bits',
|
||||
intValue: Math.pow(2, 32) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'truncates more than 32 bits (bit 33 set)',
|
||||
intValue: Math.pow(2, 28) - 1,
|
||||
bufferDecoder: createBufferDecoder(0xFF, 0xFF, 0xFF, 0xFF, 0x10),
|
||||
skip_writer: true,
|
||||
},
|
||||
{
|
||||
name: 'errors out for 11 bytes',
|
||||
intValue: Math.pow(2, 32) - 1,
|
||||
bufferDecoder: createBufferDecoder(
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
|
||||
error: true,
|
||||
skip_writer: true,
|
||||
},
|
||||
];
|
||||
return [...uint32Pairs];
|
||||
}
|
||||
|
||||
exports = {getUint32Pairs};
|
28
deps/protobuf/js/experimental/runtime/kernel/uint8arrays.js
vendored
Normal file
28
deps/protobuf/js/experimental/runtime/kernel/uint8arrays.js
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @fileoverview Helper methods for Uint8Arrays.
|
||||
*/
|
||||
goog.module('protobuf.binary.uint8arrays');
|
||||
|
||||
/**
|
||||
* Combines multiple bytes arrays (either Uint8Array or number array whose
|
||||
* values are bytes) into a single Uint8Array.
|
||||
* @param {!Array<!Uint8Array>|!Array<!Array<number>>} arrays
|
||||
* @return {!Uint8Array}
|
||||
*/
|
||||
function concatenateByteArrays(arrays) {
|
||||
let totalLength = 0;
|
||||
for (const array of arrays) {
|
||||
totalLength += array.length;
|
||||
}
|
||||
const result = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
for (const array of arrays) {
|
||||
result.set(array, offset);
|
||||
offset += array.length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
exports = {
|
||||
concatenateByteArrays,
|
||||
};
|
47
deps/protobuf/js/experimental/runtime/kernel/uint8arrays_test.js
vendored
Normal file
47
deps/protobuf/js/experimental/runtime/kernel/uint8arrays_test.js
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @fileoverview Tests for uint8arrays.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.Uint8ArraysTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays');
|
||||
|
||||
describe('concatenateByteArrays does', () => {
|
||||
it('concatenate empty array', () => {
|
||||
const byteArrays = [];
|
||||
expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array(0));
|
||||
});
|
||||
|
||||
it('concatenate Uint8Arrays', () => {
|
||||
const byteArrays = [new Uint8Array([0x01]), new Uint8Array([0x02])];
|
||||
expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array([
|
||||
0x01, 0x02
|
||||
]));
|
||||
});
|
||||
|
||||
it('concatenate array of bytes', () => {
|
||||
const byteArrays = [[0x01], [0x02]];
|
||||
expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array([
|
||||
0x01, 0x02
|
||||
]));
|
||||
});
|
||||
|
||||
it('concatenate array of non-bytes', () => {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
const byteArrays = [[40.0], [256]];
|
||||
expect(concatenateByteArrays(byteArrays)).toEqual(new Uint8Array([
|
||||
0x28, 0x00
|
||||
]));
|
||||
});
|
||||
|
||||
it('throw for null array', () => {
|
||||
expect(
|
||||
() => concatenateByteArrays(
|
||||
/** @type {!Array<!Uint8Array>} */ (/** @type {*} */ (null))))
|
||||
.toThrow();
|
||||
});
|
||||
});
|
17
deps/protobuf/js/experimental/runtime/kernel/wire_type.js
vendored
Normal file
17
deps/protobuf/js/experimental/runtime/kernel/wire_type.js
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
goog.module('protobuf.binary.WireType');
|
||||
|
||||
/**
|
||||
* Wire-format type codes, taken from proto2/public/wire_format_lite.h.
|
||||
* @enum {number}
|
||||
*/
|
||||
const WireType = {
|
||||
VARINT: 0,
|
||||
FIXED64: 1,
|
||||
DELIMITED: 2,
|
||||
START_GROUP: 3,
|
||||
END_GROUP: 4,
|
||||
FIXED32: 5,
|
||||
INVALID: 6
|
||||
};
|
||||
|
||||
exports = WireType;
|
743
deps/protobuf/js/experimental/runtime/kernel/writer.js
vendored
Normal file
743
deps/protobuf/js/experimental/runtime/kernel/writer.js
vendored
Normal file
@ -0,0 +1,743 @@
|
||||
/**
|
||||
* @fileoverview Implements Writer for writing data as the binary wire format
|
||||
* bytes array.
|
||||
*/
|
||||
goog.module('protobuf.binary.Writer');
|
||||
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const Int64 = goog.require('protobuf.Int64');
|
||||
const WireType = goog.require('protobuf.binary.WireType');
|
||||
const {POLYFILL_TEXT_ENCODING, checkFieldNumber, checkTypeUnsignedInt32, checkWireType} = goog.require('protobuf.internal.checks');
|
||||
const {concatenateByteArrays} = goog.require('protobuf.binary.uint8arrays');
|
||||
const {createTag, getTagLength} = goog.require('protobuf.binary.tag');
|
||||
const {encode} = goog.require('protobuf.binary.textencoding');
|
||||
|
||||
/**
|
||||
* Returns a valid utf-8 encoder function based on TextEncoder if available or
|
||||
* a polyfill.
|
||||
* Some of the environments we run in do not have TextEncoder defined.
|
||||
* TextEncoder is faster than our polyfill so we prefer it over the polyfill.
|
||||
* @return {function(string):!Uint8Array}
|
||||
*/
|
||||
function getEncoderFunction() {
|
||||
if (goog.global['TextEncoder']) {
|
||||
const textEncoder = new goog.global['TextEncoder']('utf-8');
|
||||
return s => s.length === 0 ? new Uint8Array(0) : textEncoder.encode(s);
|
||||
}
|
||||
if (POLYFILL_TEXT_ENCODING) {
|
||||
return encode;
|
||||
} else {
|
||||
throw new Error(
|
||||
'TextEncoder is missing. ' +
|
||||
'Enable protobuf.defines.POLYFILL_TEXT_ENCODING');
|
||||
}
|
||||
}
|
||||
|
||||
/** @const {function(string): !Uint8Array} */
|
||||
const encoderFunction = getEncoderFunction();
|
||||
|
||||
/**
|
||||
* Writer provides methods for encoding all protobuf supported type into a
|
||||
* binary format bytes array.
|
||||
* Check https://developers.google.com/protocol-buffers/docs/encoding for binary
|
||||
* format definition.
|
||||
* @final
|
||||
* @package
|
||||
*/
|
||||
class Writer {
|
||||
constructor() {
|
||||
/**
|
||||
* Blocks of data that needs to be serialized. After writing all the data,
|
||||
* the blocks are concatenated into a single Uint8Array.
|
||||
* @private {!Array<!Uint8Array>}
|
||||
*/
|
||||
this.blocks_ = [];
|
||||
|
||||
/**
|
||||
* A buffer for writing varint data (tag number + field number for each
|
||||
* field, int32, uint32 etc.). Before writing a non-varint data block
|
||||
* (string, fixed32 etc.), the buffer is appended to the block array as a
|
||||
* new block, and a new buffer is started.
|
||||
*
|
||||
* We could've written each varint as a new block instead of writing
|
||||
* multiple varints in this buffer. But this will increase the number of
|
||||
* blocks, and concatenating many small blocks is slower than concatenating
|
||||
* few large blocks.
|
||||
*
|
||||
* TODO: Experiment with writing data in a fixed-length
|
||||
* Uint8Array instead of using a growing buffer.
|
||||
*
|
||||
* @private {!Array<number>}
|
||||
*/
|
||||
this.currentBuffer_ = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the encoded data into a Uint8Array.
|
||||
* The writer is also reset.
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
getAndResetResultBuffer() {
|
||||
this.closeAndStartNewBuffer_();
|
||||
const result = concatenateByteArrays(this.blocks_);
|
||||
this.blocks_ = [];
|
||||
return result.buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a (field number, wire type) tuple into a wire-format field header.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!WireType} wireType
|
||||
*/
|
||||
writeTag(fieldNumber, wireType) {
|
||||
checkFieldNumber(fieldNumber);
|
||||
checkWireType(wireType);
|
||||
const tag = createTag(wireType, fieldNumber);
|
||||
this.writeUnsignedVarint32_(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the current buffer into the blocks array and starts a new buffer.
|
||||
* @private
|
||||
*/
|
||||
closeAndStartNewBuffer_() {
|
||||
this.blocks_.push(new Uint8Array(this.currentBuffer_));
|
||||
this.currentBuffer_ = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a 32-bit integer into its wire-format varint representation and
|
||||
* stores it in the buffer.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeUnsignedVarint32_(value) {
|
||||
checkTypeUnsignedInt32(value);
|
||||
while (value > 0x7f) {
|
||||
this.currentBuffer_.push((value & 0x7f) | 0x80);
|
||||
value = value >>> 7;
|
||||
}
|
||||
this.currentBuffer_.push(value);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OPTIONAL METHODS
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Writes a boolean value field to the buffer as a varint.
|
||||
* @param {boolean} value
|
||||
* @private
|
||||
*/
|
||||
writeBoolValue_(value) {
|
||||
this.currentBuffer_.push(value ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a boolean value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {boolean} value
|
||||
*/
|
||||
writeBool(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.VARINT);
|
||||
this.writeBoolValue_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a bytes value field to the buffer as a length delimited field.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!ByteString} value
|
||||
*/
|
||||
writeBytes(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.DELIMITED);
|
||||
const buffer = value.toArrayBuffer();
|
||||
this.writeUnsignedVarint32_(buffer.byteLength);
|
||||
this.writeRaw_(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a double value field to the buffer without tag.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeDoubleValue_(value) {
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat64(0, value, true);
|
||||
this.writeRaw_(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a double value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeDouble(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.FIXED64);
|
||||
this.writeDoubleValue_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a fixed32 value field to the buffer without tag.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeFixed32Value_(value) {
|
||||
const buffer = new ArrayBuffer(4);
|
||||
const view = new DataView(buffer);
|
||||
view.setUint32(0, value, true);
|
||||
this.writeRaw_(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a fixed32 value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeFixed32(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.FIXED32);
|
||||
this.writeFixed32Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a float value field to the buffer without tag.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeFloatValue_(value) {
|
||||
const buffer = new ArrayBuffer(4);
|
||||
const view = new DataView(buffer);
|
||||
view.setFloat32(0, value, true);
|
||||
this.writeRaw_(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a float value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeFloat(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.FIXED32);
|
||||
this.writeFloatValue_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a int32 value field to the buffer as a varint without tag.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeInt32Value_(value) {
|
||||
if (value >= 0) {
|
||||
this.writeVarint64_(0, value);
|
||||
} else {
|
||||
this.writeVarint64_(0xFFFFFFFF, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a int32 value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeInt32(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.VARINT);
|
||||
this.writeInt32Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a int64 value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Int64} value
|
||||
*/
|
||||
writeInt64(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.VARINT);
|
||||
this.writeVarint64_(value.getHighBits(), value.getLowBits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sfixed32 value field to the buffer.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeSfixed32Value_(value) {
|
||||
const buffer = new ArrayBuffer(4);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt32(0, value, true);
|
||||
this.writeRaw_(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sfixed32 value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeSfixed32(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.FIXED32);
|
||||
this.writeSfixed32Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sfixed64 value field to the buffer without tag.
|
||||
* @param {!Int64} value
|
||||
* @private
|
||||
*/
|
||||
writeSfixed64Value_(value) {
|
||||
const buffer = new ArrayBuffer(8);
|
||||
const view = new DataView(buffer);
|
||||
view.setInt32(0, value.getLowBits(), true);
|
||||
view.setInt32(4, value.getHighBits(), true);
|
||||
this.writeRaw_(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sfixed64 value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Int64} value
|
||||
*/
|
||||
writeSfixed64(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.FIXED64);
|
||||
this.writeSfixed64Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sfixed64 value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
*/
|
||||
writeStartGroup(fieldNumber) {
|
||||
this.writeTag(fieldNumber, WireType.START_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sfixed64 value field to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
*/
|
||||
writeEndGroup(fieldNumber) {
|
||||
this.writeTag(fieldNumber, WireType.END_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a uint32 value field to the buffer as a varint without tag.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeUint32Value_(value) {
|
||||
this.writeVarint64_(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a uint32 value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeUint32(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.VARINT);
|
||||
this.writeUint32Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the bits of a 64 bit number to the buffer as a varint.
|
||||
* @param {number} highBits
|
||||
* @param {number} lowBits
|
||||
* @private
|
||||
*/
|
||||
writeVarint64_(highBits, lowBits) {
|
||||
for (let i = 0; i < 28; i = i + 7) {
|
||||
const shift = lowBits >>> i;
|
||||
const hasNext = !((shift >>> 7) === 0 && highBits === 0);
|
||||
const byte = (hasNext ? shift | 0x80 : shift) & 0xFF;
|
||||
this.currentBuffer_.push(byte);
|
||||
if (!hasNext) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const splitBits = ((lowBits >>> 28) & 0x0F) | ((highBits & 0x07) << 4);
|
||||
const hasMoreBits = !((highBits >> 3) === 0);
|
||||
this.currentBuffer_.push(
|
||||
(hasMoreBits ? splitBits | 0x80 : splitBits) & 0xFF);
|
||||
|
||||
if (!hasMoreBits) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 3; i < 31; i = i + 7) {
|
||||
const shift = highBits >>> i;
|
||||
const hasNext = !((shift >>> 7) === 0);
|
||||
const byte = (hasNext ? shift | 0x80 : shift) & 0xFF;
|
||||
this.currentBuffer_.push(byte);
|
||||
if (!hasNext) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.currentBuffer_.push((highBits >>> 31) & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sint32 value field to the buffer as a varint without tag.
|
||||
* @param {number} value
|
||||
* @private
|
||||
*/
|
||||
writeSint32Value_(value) {
|
||||
value = (value << 1) ^ (value >> 31);
|
||||
this.writeVarint64_(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sint32 value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {number} value
|
||||
*/
|
||||
writeSint32(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.VARINT);
|
||||
this.writeSint32Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sint64 value field to the buffer as a varint without tag.
|
||||
* @param {!Int64} value
|
||||
* @private
|
||||
*/
|
||||
writeSint64Value_(value) {
|
||||
const highBits = value.getHighBits();
|
||||
const lowBits = value.getLowBits();
|
||||
|
||||
const sign = highBits >> 31;
|
||||
const encodedLowBits = (lowBits << 1) ^ sign;
|
||||
const encodedHighBits = ((highBits << 1) | (lowBits >>> 31)) ^ sign;
|
||||
this.writeVarint64_(encodedHighBits, encodedLowBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sint64 value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Int64} value
|
||||
*/
|
||||
writeSint64(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.VARINT);
|
||||
this.writeSint64Value_(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a string value field to the buffer as a varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {string} value
|
||||
*/
|
||||
writeString(fieldNumber, value) {
|
||||
this.writeTag(fieldNumber, WireType.DELIMITED);
|
||||
const array = encoderFunction(value);
|
||||
this.writeUnsignedVarint32_(array.length);
|
||||
this.closeAndStartNewBuffer_();
|
||||
this.blocks_.push(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes raw bytes to the buffer.
|
||||
* @param {!ArrayBuffer} arrayBuffer
|
||||
* @private
|
||||
*/
|
||||
writeRaw_(arrayBuffer) {
|
||||
this.closeAndStartNewBuffer_();
|
||||
this.blocks_.push(new Uint8Array(arrayBuffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes raw bytes to the buffer.
|
||||
* @param {!BufferDecoder} bufferDecoder
|
||||
* @param {number} start
|
||||
* @param {!WireType} wireType
|
||||
* @param {number} fieldNumber
|
||||
* @package
|
||||
*/
|
||||
writeBufferDecoder(bufferDecoder, start, wireType, fieldNumber) {
|
||||
this.closeAndStartNewBuffer_();
|
||||
const dataLength =
|
||||
getTagLength(bufferDecoder, start, wireType, fieldNumber);
|
||||
this.blocks_.push(
|
||||
bufferDecoder.subBufferDecoder(start, dataLength).asUint8Array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the whole bytes as a length delimited field.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!ArrayBuffer} arrayBuffer
|
||||
*/
|
||||
writeDelimited(fieldNumber, arrayBuffer) {
|
||||
this.writeTag(fieldNumber, WireType.DELIMITED);
|
||||
this.writeUnsignedVarint32_(arrayBuffer.byteLength);
|
||||
this.writeRaw_(arrayBuffer);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* REPEATED METHODS
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Writes repeated boolean values to the buffer as unpacked varints.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<boolean>} values
|
||||
*/
|
||||
writeRepeatedBool(fieldNumber, values) {
|
||||
values.forEach(val => this.writeBool(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated boolean values to the buffer as packed varints.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<boolean>} values
|
||||
*/
|
||||
writePackedBool(fieldNumber, values) {
|
||||
this.writeFixedPacked_(
|
||||
fieldNumber, values, val => this.writeBoolValue_(val), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated double values to the buffer as unpacked fixed64.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedDouble(fieldNumber, values) {
|
||||
values.forEach(val => this.writeDouble(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated double values to the buffer as packed fixed64.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedDouble(fieldNumber, values) {
|
||||
this.writeFixedPacked_(
|
||||
fieldNumber, values, val => this.writeDoubleValue_(val), 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated fixed32 values to the buffer as unpacked fixed32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedFixed32(fieldNumber, values) {
|
||||
values.forEach(val => this.writeFixed32(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated fixed32 values to the buffer as packed fixed32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedFixed32(fieldNumber, values) {
|
||||
this.writeFixedPacked_(
|
||||
fieldNumber, values, val => this.writeFixed32Value_(val), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated float values to the buffer as unpacked fixed64.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedFloat(fieldNumber, values) {
|
||||
values.forEach(val => this.writeFloat(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated float values to the buffer as packed fixed64.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedFloat(fieldNumber, values) {
|
||||
this.writeFixedPacked_(
|
||||
fieldNumber, values, val => this.writeFloatValue_(val), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated int32 values to the buffer as unpacked int32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedInt32(fieldNumber, values) {
|
||||
values.forEach(val => this.writeInt32(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated int32 values to the buffer as packed int32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedInt32(fieldNumber, values) {
|
||||
this.writeVariablePacked_(
|
||||
fieldNumber, values, (writer, val) => writer.writeInt32Value_(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated int64 values to the buffer as unpacked varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!Int64>} values
|
||||
*/
|
||||
writeRepeatedInt64(fieldNumber, values) {
|
||||
values.forEach(val => this.writeInt64(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated int64 values to the buffer as packed varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!Int64>} values
|
||||
*/
|
||||
writePackedInt64(fieldNumber, values) {
|
||||
this.writeVariablePacked_(
|
||||
fieldNumber, values,
|
||||
(writer, val) =>
|
||||
writer.writeVarint64_(val.getHighBits(), val.getLowBits()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sfixed32 values to the buffer as unpacked fixed32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedSfixed32(fieldNumber, values) {
|
||||
values.forEach(val => this.writeSfixed32(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sfixed32 values to the buffer as packed fixed32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedSfixed32(fieldNumber, values) {
|
||||
this.writeFixedPacked_(
|
||||
fieldNumber, values, val => this.writeSfixed32Value_(val), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sfixed64 values to the buffer as unpacked fixed64.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!Int64>} values
|
||||
*/
|
||||
writeRepeatedSfixed64(fieldNumber, values) {
|
||||
values.forEach(val => this.writeSfixed64(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sfixed64 values to the buffer as packed fixed64.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!Int64>} values
|
||||
*/
|
||||
writePackedSfixed64(fieldNumber, values) {
|
||||
this.writeFixedPacked_(
|
||||
fieldNumber, values, val => this.writeSfixed64Value_(val), 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sint32 values to the buffer as unpacked sint32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedSint32(fieldNumber, values) {
|
||||
values.forEach(val => this.writeSint32(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sint32 values to the buffer as packed sint32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedSint32(fieldNumber, values) {
|
||||
this.writeVariablePacked_(
|
||||
fieldNumber, values, (writer, val) => writer.writeSint32Value_(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sint64 values to the buffer as unpacked varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!Int64>} values
|
||||
*/
|
||||
writeRepeatedSint64(fieldNumber, values) {
|
||||
values.forEach(val => this.writeSint64(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated sint64 values to the buffer as packed varint.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!Int64>} values
|
||||
*/
|
||||
writePackedSint64(fieldNumber, values) {
|
||||
this.writeVariablePacked_(
|
||||
fieldNumber, values, (writer, val) => writer.writeSint64Value_(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated uint32 values to the buffer as unpacked uint32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writeRepeatedUint32(fieldNumber, values) {
|
||||
values.forEach(val => this.writeUint32(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated uint32 values to the buffer as packed uint32.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<number>} values
|
||||
*/
|
||||
writePackedUint32(fieldNumber, values) {
|
||||
this.writeVariablePacked_(
|
||||
fieldNumber, values, (writer, val) => writer.writeUint32Value_(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated bytes values to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<!ByteString>} values
|
||||
*/
|
||||
writeRepeatedBytes(fieldNumber, values) {
|
||||
values.forEach(val => this.writeBytes(fieldNumber, val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes packed fields with fixed length.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<T>} values
|
||||
* @param {function(T)} valueWriter
|
||||
* @param {number} entitySize
|
||||
* @template T
|
||||
* @private
|
||||
*/
|
||||
writeFixedPacked_(fieldNumber, values, valueWriter, entitySize) {
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.writeTag(fieldNumber, WireType.DELIMITED);
|
||||
this.writeUnsignedVarint32_(values.length * entitySize);
|
||||
this.closeAndStartNewBuffer_();
|
||||
values.forEach(value => valueWriter(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes packed fields with variable length.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<T>} values
|
||||
* @param {function(!Writer, T)} valueWriter
|
||||
* @template T
|
||||
* @private
|
||||
*/
|
||||
writeVariablePacked_(fieldNumber, values, valueWriter) {
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
}
|
||||
const writer = new Writer();
|
||||
values.forEach(val => valueWriter(writer, val));
|
||||
const bytes = writer.getAndResetResultBuffer();
|
||||
this.writeDelimited(fieldNumber, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes repeated string values to the buffer.
|
||||
* @param {number} fieldNumber
|
||||
* @param {!Array<string>} values
|
||||
*/
|
||||
writeRepeatedString(fieldNumber, values) {
|
||||
values.forEach(val => this.writeString(fieldNumber, val));
|
||||
}
|
||||
}
|
||||
|
||||
exports = Writer;
|
927
deps/protobuf/js/experimental/runtime/kernel/writer_test.js
vendored
Normal file
927
deps/protobuf/js/experimental/runtime/kernel/writer_test.js
vendored
Normal file
@ -0,0 +1,927 @@
|
||||
/**
|
||||
* @fileoverview Tests for writer.js.
|
||||
*/
|
||||
goog.module('protobuf.binary.WriterTest');
|
||||
|
||||
goog.setTestOnly();
|
||||
|
||||
// Note to the reader:
|
||||
// Since the writer behavior changes with the checking level some of the tests
|
||||
// in this file have to know which checking level is enable to make correct
|
||||
// assertions.
|
||||
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
|
||||
const ByteString = goog.require('protobuf.ByteString');
|
||||
const WireType = goog.require('protobuf.binary.WireType');
|
||||
const Writer = goog.require('protobuf.binary.Writer');
|
||||
const {CHECK_BOUNDS, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks');
|
||||
const {arrayBufferSlice} = goog.require('protobuf.binary.typedArrays');
|
||||
const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs');
|
||||
const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs');
|
||||
const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs');
|
||||
const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs');
|
||||
const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs');
|
||||
const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs');
|
||||
const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs');
|
||||
const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs');
|
||||
const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs');
|
||||
const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs');
|
||||
const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs');
|
||||
const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs');
|
||||
const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs');
|
||||
const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs');
|
||||
const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs');
|
||||
const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs');
|
||||
const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs');
|
||||
const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs');
|
||||
const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs');
|
||||
const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs');
|
||||
const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs');
|
||||
|
||||
|
||||
/**
|
||||
* @param {...number} bytes
|
||||
* @return {!ArrayBuffer}
|
||||
*/
|
||||
function createArrayBuffer(...bytes) {
|
||||
return new Uint8Array(bytes).buffer;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* OPTIONAL FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
describe('Writer does', () => {
|
||||
it('return an empty ArrayBuffer when nothing is encoded', () => {
|
||||
const writer = new Writer();
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
it('encode tag', () => {
|
||||
const writer = new Writer();
|
||||
writer.writeTag(1, WireType.VARINT);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
|
||||
|
||||
writer.writeTag(0x0FFFFFFF, WireType.VARINT);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x7));
|
||||
|
||||
writer.writeTag(0x10000000, WireType.VARINT);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(0x80, 0x80, 0x80, 0x80, 0x08));
|
||||
|
||||
writer.writeTag(0x1FFFFFFF, WireType.VARINT);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F));
|
||||
});
|
||||
|
||||
it('reset after calling getAndResetResultBuffer', () => {
|
||||
const writer = new Writer();
|
||||
writer.writeTag(1, WireType.VARINT);
|
||||
writer.getAndResetResultBuffer();
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
it('fail when field number is too large for writeTag', () => {
|
||||
const writer = new Writer();
|
||||
if (CHECK_TYPE) {
|
||||
expect(() => writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT))
|
||||
.toThrowError('Field number is out of range: 536870912');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail when field number is negative for writeTag', () => {
|
||||
const writer = new Writer();
|
||||
if (CHECK_TYPE) {
|
||||
expect(() => writer.writeTag(-1, WireType.VARINT))
|
||||
.toThrowError('Field number is out of range: -1');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
writer.writeTag(-1, WireType.VARINT);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0xF));
|
||||
}
|
||||
});
|
||||
|
||||
it('fail when wire type is invalid for writeTag', () => {
|
||||
const writer = new Writer();
|
||||
if (CHECK_TYPE) {
|
||||
expect(() => writer.writeTag(1, /** @type {!WireType} */ (0x08)))
|
||||
.toThrowError('Invalid wire type: 8');
|
||||
} else {
|
||||
// Note in unchecked mode we produce invalid output for invalid inputs.
|
||||
// This test just documents our behavior in those cases.
|
||||
// These values might change at any point and are not considered
|
||||
// what the implementation should be doing here.
|
||||
writer.writeTag(1, /** @type {!WireType} */ (0x08));
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
|
||||
}
|
||||
});
|
||||
|
||||
it('encode singular boolean value', () => {
|
||||
const writer = new Writer();
|
||||
writer.writeBool(1, true);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(0x08, 0x01));
|
||||
});
|
||||
|
||||
it('encode length delimited', () => {
|
||||
const writer = new Writer();
|
||||
writer.writeDelimited(1, createArrayBuffer(0x01, 0x02));
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(0x0A, 0x02, 0x01, 0x02));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writeBufferDecoder does', () => {
|
||||
it('encode BufferDecoder containing a varint value', () => {
|
||||
const writer = new Writer();
|
||||
const expected = createArrayBuffer(
|
||||
0x08, /* varint start= */ 0xFF, /* varint end= */ 0x01, 0x08, 0x01);
|
||||
writer.writeBufferDecoder(
|
||||
BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT, 1);
|
||||
const result = writer.getAndResetResultBuffer();
|
||||
expect(result).toEqual(arrayBufferSlice(expected, 1, 3));
|
||||
});
|
||||
|
||||
it('encode BufferDecoder containing a fixed64 value', () => {
|
||||
const writer = new Writer();
|
||||
const expected = createArrayBuffer(
|
||||
0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
/* fixed64 end= */ 0x08, 0x08, 0x01);
|
||||
writer.writeBufferDecoder(
|
||||
BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64, 1);
|
||||
const result = writer.getAndResetResultBuffer();
|
||||
expect(result).toEqual(arrayBufferSlice(expected, 1, 9));
|
||||
});
|
||||
|
||||
it('encode BufferDecoder containing a length delimited value', () => {
|
||||
const writer = new Writer();
|
||||
const expected = createArrayBuffer(
|
||||
0xA, /* length= */ 0x03, /* data start= */ 0x01, 0x02,
|
||||
/* data end= */ 0x03, 0x08, 0x01);
|
||||
writer.writeBufferDecoder(
|
||||
BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED, 1);
|
||||
const result = writer.getAndResetResultBuffer();
|
||||
expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
|
||||
});
|
||||
|
||||
it('encode BufferDecoder containing a group', () => {
|
||||
const writer = new Writer();
|
||||
const expected = createArrayBuffer(
|
||||
0xB, /* group start= */ 0x08, 0x01, /* nested group start= */ 0x0B,
|
||||
/* nested group end= */ 0x0C, /* group end= */ 0x0C, 0x08, 0x01);
|
||||
writer.writeBufferDecoder(
|
||||
BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP, 1);
|
||||
const result = writer.getAndResetResultBuffer();
|
||||
expect(result).toEqual(arrayBufferSlice(expected, 1, 6));
|
||||
});
|
||||
|
||||
it('encode BufferDecoder containing a fixed32 value', () => {
|
||||
const writer = new Writer();
|
||||
const expected = createArrayBuffer(
|
||||
0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, /* fixed64 end= */ 0x04,
|
||||
0x08, 0x01);
|
||||
writer.writeBufferDecoder(
|
||||
BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32, 1);
|
||||
const result = writer.getAndResetResultBuffer();
|
||||
expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
|
||||
});
|
||||
|
||||
it('fail when encoding out of bound data', () => {
|
||||
const writer = new Writer();
|
||||
const buffer = createArrayBuffer(0x4, 0x0, 0x1, 0x2, 0x3);
|
||||
const subBuffer = arrayBufferSlice(buffer, 0, 2);
|
||||
expect(
|
||||
() => writer.writeBufferDecoder(
|
||||
BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED, 1))
|
||||
.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writeBytes does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encodes empty ByteString', () => {
|
||||
writer.writeBytes(1, ByteString.EMPTY);
|
||||
const buffer = writer.getAndResetResultBuffer();
|
||||
expect(buffer.byteLength).toBe(2);
|
||||
});
|
||||
|
||||
it('encodes empty array', () => {
|
||||
writer.writeBytes(1, ByteString.fromArrayBuffer(new ArrayBuffer(0)));
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
|
||||
0, // length of the bytes
|
||||
));
|
||||
});
|
||||
|
||||
it('encodes ByteString', () => {
|
||||
const array = createArrayBuffer(1, 2, 3);
|
||||
writer.writeBytes(1, ByteString.fromArrayBuffer(array));
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
|
||||
3, // length of the bytes
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writeDouble does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getDoublePairs()) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeDouble(1, pair.doubleValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(9);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x09);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, 9))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* NaN may have different value in different browsers. Thus, we need to make
|
||||
* the test lenient.
|
||||
*/
|
||||
it('encode NaN', () => {
|
||||
writer.writeDouble(1, NaN);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(9);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x09);
|
||||
// Encoded values are stored right after the tag
|
||||
const float64 = new DataView(buffer.buffer);
|
||||
expect(float64.getFloat64(1, true)).toBeNaN();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writeFixed32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getFixed32Pairs()) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeFixed32(1, pair.intValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(5);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0D);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeFloat does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getFloatPairs()) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeFloat(1, pair.floatValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(5);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0D);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* NaN may have different value in different browsers. Thus, we need to make
|
||||
* the test lenient.
|
||||
*/
|
||||
it('encode NaN', () => {
|
||||
writer.writeFloat(1, NaN);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(5);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0D);
|
||||
// Encoded values are stored right after the tag
|
||||
const float32 = new DataView(buffer.buffer);
|
||||
expect(float32.getFloat32(1, true)).toBeNaN();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writeInt32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getInt32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeInt32(1, pair.intValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x08);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeSfixed32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedSfixed32(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getSfixed32Pairs()) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeSfixed32(1, pair.intValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(5);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0D);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeSfixed64 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getSfixed64Pairs()) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeSfixed64(1, pair.longValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
expect(buffer.length).toBe(9);
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x09);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, 9)).toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeSint32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getSint32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeSint32(1, pair.intValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x08);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeSint64 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getSint64Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeSint64(1, pair.longValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x08);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeInt64 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getInt64Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeInt64(1, pair.longValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x08);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeUint32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
for (const pair of getUint32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writeUint32(1, pair.intValue);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x08);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeString does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty string', () => {
|
||||
writer.writeString(1, '');
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
|
||||
0, // length of the string
|
||||
));
|
||||
});
|
||||
|
||||
it('encode simple string', () => {
|
||||
writer.writeString(1, 'hello');
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
|
||||
5, // length of the string
|
||||
'h'.charCodeAt(0),
|
||||
'e'.charCodeAt(0),
|
||||
'l'.charCodeAt(0),
|
||||
'l'.charCodeAt(0),
|
||||
'o'.charCodeAt(0),
|
||||
));
|
||||
});
|
||||
|
||||
it('throw for invalid fieldnumber', () => {
|
||||
if (CHECK_BOUNDS) {
|
||||
expect(() => writer.writeString(-1, 'a'))
|
||||
.toThrowError('Field number is out of range: -1');
|
||||
} else {
|
||||
writer.writeString(-1, 'a');
|
||||
expect(new Uint8Array(writer.getAndResetResultBuffer()))
|
||||
.toEqual(new Uint8Array(createArrayBuffer(
|
||||
-6, // invalid tag
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
0x0f,
|
||||
1, // string length
|
||||
'a'.charCodeAt(0),
|
||||
)));
|
||||
}
|
||||
});
|
||||
|
||||
it('throw for null string value', () => {
|
||||
expect(
|
||||
() => writer.writeString(
|
||||
1, /** @type {string} */ (/** @type {*} */ (null))))
|
||||
.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* REPEATED FUNCTIONS
|
||||
******************************************************************************/
|
||||
|
||||
describe('Writer.writePackedBool does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedBool(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedBoolPairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedBool(1, pair.boolValues);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeRepeatedBool does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writeRepeatedBool(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
it('encode repeated unpacked boolean values', () => {
|
||||
const writer = new Writer();
|
||||
writer.writeRepeatedBool(1, [true, false]);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint))
|
||||
0x01, // value[0]
|
||||
1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint))
|
||||
0x00, // value[1]
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writePackedDouble does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedDouble(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedDoublePairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedDouble(1, pair.doubleValues);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedFixed32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedFixed32(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedFixed32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedFixed32(1, pair.fixed32Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedFloat does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedFloat(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedFloatPairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedFloat(1, pair.floatValues);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedInt32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedInt32(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedInt32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedInt32(1, pair.int32Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedInt64 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedInt64(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedInt64Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedInt64(1, pair.int64Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedSfixed32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedSfixed32(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedSfixed32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedSfixed32(1, pair.sfixed32Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedSfixed64 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedSfixed64(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedSfixed64Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedSfixed64(1, pair.sfixed64Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedSint32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedSint32(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedSint32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedSint32(1, pair.sint32Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedSint64 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedSint64(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedSint64Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedSint64(1, pair.sint64Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writePackedUint32 does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writePackedUint32(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
for (const pair of getPackedUint32Pairs()) {
|
||||
if (!pair.skip_writer) {
|
||||
it(`encode ${pair.name}`, () => {
|
||||
writer.writePackedUint32(1, pair.uint32Values);
|
||||
const buffer = new Uint8Array(writer.getAndResetResultBuffer());
|
||||
// ensure we have a correct tag
|
||||
expect(buffer[0]).toEqual(0x0A);
|
||||
// Encoded values are stored right after the tag
|
||||
expect(buffer.subarray(1, buffer.length))
|
||||
.toEqual(pair.bufferDecoder.asUint8Array());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('Writer.writeRepeatedBytes does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writeRepeatedBytes(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
it('encode single value', () => {
|
||||
const value = createArrayBuffer(0x61);
|
||||
writer.writeRepeatedBytes(1, [ByteString.fromArrayBuffer(value)]);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
0x0A,
|
||||
0x01,
|
||||
0x61, // a
|
||||
));
|
||||
});
|
||||
|
||||
it('encode multiple values', () => {
|
||||
const value1 = createArrayBuffer(0x61);
|
||||
const value2 = createArrayBuffer(0x62);
|
||||
writer.writeRepeatedBytes(1, [
|
||||
ByteString.fromArrayBuffer(value1),
|
||||
ByteString.fromArrayBuffer(value2),
|
||||
]);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
0x0A,
|
||||
0x01,
|
||||
0x61, // a
|
||||
0x0A,
|
||||
0x01,
|
||||
0x62, // b
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Writer.writeRepeatedString does', () => {
|
||||
let writer;
|
||||
beforeEach(() => {
|
||||
writer = new Writer();
|
||||
});
|
||||
|
||||
it('encode empty array', () => {
|
||||
writer.writeRepeatedString(1, []);
|
||||
expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
|
||||
});
|
||||
|
||||
it('encode single value', () => {
|
||||
writer.writeRepeatedString(1, ['a']);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
0x0A,
|
||||
0x01,
|
||||
0x61, // a
|
||||
));
|
||||
});
|
||||
|
||||
it('encode multiple values', () => {
|
||||
writer.writeRepeatedString(1, ['a', 'b']);
|
||||
expect(writer.getAndResetResultBuffer())
|
||||
.toEqual(createArrayBuffer(
|
||||
0x0A,
|
||||
0x01,
|
||||
0x61, // a
|
||||
0x0A,
|
||||
0x01,
|
||||
0x62, // b
|
||||
));
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user