Skip to content

Commit 7b80ba2

Browse files
rafi-kamalcopybara-github
authored andcommitted
Project import generated by Copybara
PiperOrigin-RevId: 301311140
1 parent 3664b8a commit 7b80ba2

6 files changed

Lines changed: 178 additions & 113 deletions

File tree

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
goog.module('protobuf.runtime.BinaryStorage');
2+
3+
const Storage = goog.require('protobuf.runtime.Storage');
4+
const {checkDefAndNotNull} = goog.require('protobuf.internal.checks');
5+
6+
/**
7+
* Class storing all the fields of a binary protobuf message.
8+
*
9+
* @package
10+
* @template FieldType
11+
* @implements {Storage}
12+
*/
13+
class BinaryStorage {
14+
/**
15+
* @param {number=} pivot
16+
*/
17+
constructor(pivot = Storage.DEFAULT_PIVOT) {
18+
/**
19+
* Fields having a field number no greater than the pivot value are stored
20+
* into an array for fast access. A field with field number X is stored into
21+
* the array position X - 1.
22+
*
23+
* @private @const {!Array<!FieldType|undefined>}
24+
*/
25+
this.array_ = new Array(pivot);
26+
27+
/**
28+
* Fields having a field number higher than the pivot value are stored into
29+
* the map. We create the map only when it's needed, since even an empty map
30+
* takes up a significant amount of memory.
31+
*
32+
* @private {?Map<number, !FieldType>}
33+
*/
34+
this.map_ = null;
35+
}
36+
37+
/**
38+
* Fields having a field number no greater than the pivot value are stored
39+
* into an array for fast access. A field with field number X is stored into
40+
* the array position X - 1.
41+
* @return {number}
42+
* @override
43+
*/
44+
getPivot() {
45+
return this.array_.length;
46+
}
47+
48+
/**
49+
* Sets a field in the specified field number.
50+
*
51+
* @param {number} fieldNumber
52+
* @param {!FieldType} field
53+
* @override
54+
*/
55+
set(fieldNumber, field) {
56+
if (fieldNumber <= this.getPivot()) {
57+
this.array_[fieldNumber - 1] = field;
58+
} else {
59+
if (this.map_) {
60+
this.map_.set(fieldNumber, field);
61+
} else {
62+
this.map_ = new Map([[fieldNumber, field]]);
63+
}
64+
}
65+
}
66+
67+
/**
68+
* Returns a field at the specified field number.
69+
*
70+
* @param {number} fieldNumber
71+
* @return {!FieldType|undefined}
72+
* @override
73+
*/
74+
get(fieldNumber) {
75+
if (fieldNumber <= this.getPivot()) {
76+
return this.array_[fieldNumber - 1];
77+
} else {
78+
return this.map_ ? this.map_.get(fieldNumber) : undefined;
79+
}
80+
}
81+
82+
/**
83+
* Deletes a field from the specified field number.
84+
*
85+
* @param {number} fieldNumber
86+
* @override
87+
*/
88+
delete(fieldNumber) {
89+
if (fieldNumber <= this.getPivot()) {
90+
delete this.array_[fieldNumber - 1];
91+
} else {
92+
if (this.map_) {
93+
this.map_.delete(fieldNumber);
94+
}
95+
}
96+
}
97+
98+
/**
99+
* Executes the provided function once for each field.
100+
*
101+
* @param {function(!FieldType, number): void} callback
102+
* @override
103+
*/
104+
forEach(callback) {
105+
this.array_.forEach((field, fieldNumber) => {
106+
if (field) {
107+
callback(checkDefAndNotNull(field), fieldNumber + 1);
108+
}
109+
});
110+
if (this.map_) {
111+
this.map_.forEach(callback);
112+
}
113+
}
114+
115+
/**
116+
* Creates a shallow copy of the storage.
117+
*
118+
* @return {!BinaryStorage}
119+
* @override
120+
*/
121+
shallowCopy() {
122+
const copy = new BinaryStorage(this.getPivot());
123+
this.forEach(
124+
(field, fieldNumber) =>
125+
void copy.set(fieldNumber, field.shallowCopy()));
126+
return copy;
127+
}
128+
}
129+
130+
exports = BinaryStorage;

experimental/runtime/kernel/storage_test.js renamed to experimental/runtime/kernel/binary_storage_test.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/**
22
* @fileoverview Tests for storage.js.
33
*/
4-
goog.module('protobuf.binary.StorageTest');
4+
goog.module('protobuf.runtime.BinaryStorageTest');
55

66
goog.setTestOnly();
77

8-
const Storage = goog.require('protobuf.binary.Storage');
8+
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
99
const {Field} = goog.require('protobuf.binary.field');
1010

1111
/**
@@ -25,7 +25,7 @@ const /** !Field */ field4 =
2525
/**
2626
* Returns the number of fields stored.
2727
*
28-
* @param {!Storage} storage
28+
* @param {!BinaryStorage} storage
2929
* @return {number}
3030
*/
3131
function getStorageSize(storage) {
@@ -34,9 +34,9 @@ function getStorageSize(storage) {
3434
return size;
3535
}
3636

37-
describe('Storage', () => {
37+
describe('BinaryStorage', () => {
3838
it('sets and gets a field not greater than the pivot', () => {
39-
const storage = new Storage(DEFAULT_PIVOT);
39+
const storage = new BinaryStorage(DEFAULT_PIVOT);
4040

4141
storage.set(1, field1);
4242
storage.set(DEFAULT_PIVOT, field2);
@@ -47,7 +47,7 @@ describe('Storage', () => {
4747
});
4848

4949
it('sets and gets a field greater than the pivot', () => {
50-
const storage = new Storage(DEFAULT_PIVOT);
50+
const storage = new BinaryStorage(DEFAULT_PIVOT);
5151

5252
storage.set(DEFAULT_PIVOT + 1, field1);
5353
storage.set(100000, field2);
@@ -57,7 +57,7 @@ describe('Storage', () => {
5757
});
5858

5959
it('sets and gets a field when pivot is zero', () => {
60-
const storage = new Storage(0);
60+
const storage = new BinaryStorage(0);
6161

6262
storage.set(0, field1);
6363
storage.set(100000, field2);
@@ -68,7 +68,7 @@ describe('Storage', () => {
6868
});
6969

7070
it('sets and gets a field when pivot is undefined', () => {
71-
const storage = new Storage();
71+
const storage = new BinaryStorage();
7272

7373
storage.set(0, field1);
7474
storage.set(DEFAULT_PIVOT, field2);
@@ -81,7 +81,7 @@ describe('Storage', () => {
8181
});
8282

8383
it('returns undefined for nonexistent fields', () => {
84-
const storage = new Storage(DEFAULT_PIVOT);
84+
const storage = new BinaryStorage(DEFAULT_PIVOT);
8585

8686
expect(storage.get(1)).toBeUndefined();
8787
expect(storage.get(DEFAULT_PIVOT)).toBeUndefined();
@@ -91,7 +91,7 @@ describe('Storage', () => {
9191

9292
it('returns undefined for nonexistent fields after map initialization',
9393
() => {
94-
const storage = new Storage(DEFAULT_PIVOT);
94+
const storage = new BinaryStorage(DEFAULT_PIVOT);
9595
storage.set(100001, field1);
9696

9797
expect(storage.get(1)).toBeUndefined();
@@ -101,7 +101,7 @@ describe('Storage', () => {
101101
});
102102

103103
it('deletes a field in delete() when values are only in array', () => {
104-
const storage = new Storage(DEFAULT_PIVOT);
104+
const storage = new BinaryStorage(DEFAULT_PIVOT);
105105
storage.set(1, field1);
106106

107107
storage.delete(1);
@@ -111,7 +111,7 @@ describe('Storage', () => {
111111

112112
it('deletes a field in delete() when values are both in array and map',
113113
() => {
114-
const storage = new Storage(DEFAULT_PIVOT);
114+
const storage = new BinaryStorage(DEFAULT_PIVOT);
115115
storage.set(DEFAULT_PIVOT, field2);
116116
storage.set(DEFAULT_PIVOT + 1, field3);
117117

@@ -123,7 +123,7 @@ describe('Storage', () => {
123123
});
124124

125125
it('deletes a field in delete() when values are only in map', () => {
126-
const storage = new Storage(DEFAULT_PIVOT);
126+
const storage = new BinaryStorage(DEFAULT_PIVOT);
127127
storage.set(100000, field4);
128128

129129
storage.delete(100000);
@@ -132,7 +132,7 @@ describe('Storage', () => {
132132
});
133133

134134
it('loops over all the elements in forEach()', () => {
135-
const storage = new Storage(DEFAULT_PIVOT);
135+
const storage = new BinaryStorage(DEFAULT_PIVOT);
136136
storage.set(1, field1);
137137
storage.set(DEFAULT_PIVOT, field2);
138138
storage.set(DEFAULT_PIVOT + 1, field3);
@@ -150,7 +150,7 @@ describe('Storage', () => {
150150
});
151151

152152
it('creates a shallow copy of the storage in shallowCopy()', () => {
153-
const storage = new Storage(DEFAULT_PIVOT);
153+
const storage = new BinaryStorage(DEFAULT_PIVOT);
154154
storage.set(1, field1);
155155
storage.set(100000, field2);
156156

experimental/runtime/kernel/indexer.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
*/
55
goog.module('protobuf.binary.indexer');
66

7+
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
78
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
8-
const Storage = goog.require('protobuf.binary.Storage');
99
const WireType = goog.require('protobuf.binary.WireType');
1010
const {Field} = goog.require('protobuf.binary.field');
1111
const {checkCriticalElementIndex, checkCriticalState} = goog.require('protobuf.internal.checks');
1212

1313
/**
1414
* Appends a new entry in the index array for the given field number.
15-
* @param {!Storage<!Field>} storage
15+
* @param {!BinaryStorage<!Field>} storage
1616
* @param {number} fieldNumber
1717
* @param {!WireType} wireType
1818
* @param {number} startIndex
@@ -50,13 +50,13 @@ function tagToFieldNumber(tag) {
5050
* Creates an index of field locations in a given binary protobuf.
5151
* @param {!BufferDecoder} bufferDecoder
5252
* @param {number|undefined} pivot
53-
* @return {!Storage<!Field>}
53+
* @return {!BinaryStorage<!Field>}
5454
* @package
5555
*/
5656
function buildIndex(bufferDecoder, pivot) {
5757
bufferDecoder.setCursor(bufferDecoder.startIndex());
5858

59-
const storage = new Storage(pivot);
59+
const storage = new BinaryStorage(pivot);
6060
while (bufferDecoder.hasNext()) {
6161
const tag = bufferDecoder.getUnsignedVarint32();
6262
const wireType = tagToWireType(tag);

experimental/runtime/kernel/indexer_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ goog.setTestOnly();
1010
// in this file have to know which checking level is enabled to make correct
1111
// assertions.
1212
// Test are run in all checking levels.
13+
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
1314
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
14-
const Storage = goog.require('protobuf.binary.Storage');
1515
const WireType = goog.require('protobuf.binary.WireType');
1616
const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
1717
const {Field, IndexEntry} = goog.require('protobuf.binary.field');
@@ -21,7 +21,7 @@ const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper'
2121
/**
2222
* Returns the number of fields stored.
2323
*
24-
* @param {!Storage} storage
24+
* @param {!BinaryStorage} storage
2525
* @return {number}
2626
*/
2727
function getStorageSize(storage) {
@@ -37,7 +37,7 @@ const PIVOT = 1;
3737

3838
/**
3939
* Asserts a single IndexEntry at a given field number.
40-
* @param {!Storage} storage
40+
* @param {!BinaryStorage} storage
4141
* @param {number} fieldNumber
4242
* @param {...!IndexEntry} expectedEntries
4343
*/

experimental/runtime/kernel/kernel.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
*/
1515
goog.module('protobuf.runtime.Kernel');
1616

17+
const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
1718
const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
1819
const ByteString = goog.require('protobuf.ByteString');
1920
const Int64 = goog.require('protobuf.Int64');
2021
const InternalMessage = goog.require('protobuf.binary.InternalMessage');
21-
const Storage = goog.require('protobuf.binary.Storage');
22+
const Storage = goog.require('protobuf.runtime.Storage');
2223
const WireType = goog.require('protobuf.binary.WireType');
2324
const Writer = goog.require('protobuf.binary.Writer');
2425
const reader = goog.require('protobuf.binary.reader');
@@ -278,7 +279,7 @@ class Kernel {
278279
* @return {!Kernel}
279280
*/
280281
static createEmpty(pivot = undefined) {
281-
return new Kernel(/* bufferDecoder= */ null, new Storage(pivot));
282+
return new Kernel(/* bufferDecoder= */ null, new BinaryStorage(pivot));
282283
}
283284

284285
/**

0 commit comments

Comments
 (0)