131 lines
3.1 KiB
JavaScript
131 lines
3.1 KiB
JavaScript
|
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;
|