-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathbinary_storage.js
130 lines (120 loc) · 3.06 KB
/
binary_storage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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;