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} */ 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} */ 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;