| 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; |