• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Helper methods for reading data from the binary wire format.
3 */
4goog.module('protobuf.binary.reader');
5
6const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
7const ByteString = goog.require('protobuf.ByteString');
8const Int64 = goog.require('protobuf.Int64');
9const {checkState} = goog.require('protobuf.internal.checks');
10
11
12/******************************************************************************
13 *                        OPTIONAL FUNCTIONS
14 ******************************************************************************/
15
16/**
17 * Reads a boolean value from the binary bytes.
18 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
19 * @param {number} start Start of the data.
20 * @return {boolean}
21 * @package
22 */
23function readBool(bufferDecoder, start) {
24  const {lowBits, highBits} = bufferDecoder.getVarint(start);
25  return lowBits !== 0 || highBits !== 0;
26}
27
28/**
29 * Reads a ByteString value from the binary bytes.
30 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
31 * @param {number} start Start of the data.
32 * @return {!ByteString}
33 * @package
34 */
35function readBytes(bufferDecoder, start) {
36  return readDelimited(bufferDecoder, start).asByteString();
37}
38
39/**
40 * Reads a int32 value from the binary bytes encoded as varint.
41 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
42 * @param {number} start Start of the data.
43 * @return {number}
44 * @package
45 */
46function readInt32(bufferDecoder, start) {
47  // Negative 32 bit integers are encoded with 64 bit values.
48  // Clients are expected to truncate back to 32 bits.
49  // This is why we are dropping the upper bytes here.
50  return bufferDecoder.getUnsignedVarint32At(start) | 0;
51}
52
53/**
54 * Reads a int32 value from the binary bytes encoded as varint.
55 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
56 * @param {number} start Start of the data.
57 * @return {!Int64}
58 * @package
59 */
60function readInt64(bufferDecoder, start) {
61  const {lowBits, highBits} = bufferDecoder.getVarint(start);
62  return Int64.fromBits(lowBits, highBits);
63}
64
65/**
66 * Reads a fixed int32 value from the binary bytes.
67 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
68 * @param {number} start Start of the data.
69 * @return {number}
70 * @package
71 */
72function readFixed32(bufferDecoder, start) {
73  return bufferDecoder.getUint32(start);
74}
75
76/**
77 * Reads a float value from the binary bytes.
78 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
79 * @param {number} start Start of the data.
80 * @return {number}
81 * @package
82 */
83function readFloat(bufferDecoder, start) {
84  return bufferDecoder.getFloat32(start);
85}
86
87/**
88 * Reads a fixed int64 value from the binary bytes.
89 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
90 * @param {number} start Start of the data.
91 * @return {!Int64}
92 * @package
93 */
94function readSfixed64(bufferDecoder, start) {
95  const lowBits = bufferDecoder.getInt32(start);
96  const highBits = bufferDecoder.getInt32(start + 4);
97  return Int64.fromBits(lowBits, highBits);
98}
99
100/**
101 * Reads a sint32 value from the binary bytes encoded as varint.
102 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
103 * @param {number} start Start of the data.
104 * @return {number}
105 * @package
106 */
107function readSint32(bufferDecoder, start) {
108  const bits = bufferDecoder.getUnsignedVarint32At(start);
109  // Truncate upper bits and convert from zig zag to signd int
110  return (bits >>> 1) ^ -(bits & 0x01);
111}
112
113/**
114 * Reads a sint64 value from the binary bytes encoded as varint.
115 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
116 * @param {number} start Start of the data.
117 * @return {!Int64}
118 * @package
119 */
120function readSint64(bufferDecoder, start) {
121  const {lowBits, highBits} = bufferDecoder.getVarint(start);
122  const sign = -(lowBits & 0x01);
123  const decodedLowerBits = ((lowBits >>> 1) | (highBits & 0x01) << 31) ^ sign;
124  const decodedUpperBits = (highBits >>> 1) ^ sign;
125  return Int64.fromBits(decodedLowerBits, decodedUpperBits);
126}
127
128/**
129 * Read a subarray of bytes representing a length delimited field.
130 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
131 * @param {number} start Start of the data.
132 * @return {!BufferDecoder}
133 * @package
134 */
135function readDelimited(bufferDecoder, start) {
136  const unsignedLength = bufferDecoder.getUnsignedVarint32At(start);
137  return bufferDecoder.subBufferDecoder(bufferDecoder.cursor(), unsignedLength);
138}
139
140/**
141 * Reads a string value from the binary bytes.
142 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
143 * @param {number} start Start of the data.
144 * @return {string}
145 * @package
146 */
147function readString(bufferDecoder, start) {
148  return readDelimited(bufferDecoder, start).asString();
149}
150
151/**
152 * Reads a uint32 value from the binary bytes encoded as varint.
153 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
154 * @param {number} start Start of the data.
155 * @return {number}
156 * @package
157 */
158function readUint32(bufferDecoder, start) {
159  return bufferDecoder.getUnsignedVarint32At(start);
160}
161
162/**
163 * Reads a double value from the binary bytes.
164 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
165 * @param {number} start Start of the data.
166 * @return {number}
167 * @package
168 */
169function readDouble(bufferDecoder, start) {
170  return bufferDecoder.getFloat64(start);
171}
172
173/**
174 * Reads a fixed int32 value from the binary bytes.
175 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
176 * @param {number} start Start of the data.
177 * @return {number}
178 * @package
179 */
180function readSfixed32(bufferDecoder, start) {
181  return bufferDecoder.getInt32(start);
182}
183
184/******************************************************************************
185 *                        REPEATED FUNCTIONS
186 ******************************************************************************/
187
188/**
189 * Reads a packed bool field, which consists of a length header and a list of
190 * unsigned varints.
191 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
192 * @param {number} start Start of the data.
193 * @return {!Array<boolean>}
194 * @package
195 */
196function readPackedBool(bufferDecoder, start) {
197  return readPacked(bufferDecoder, start, readBool);
198}
199
200/**
201 * Reads a packed double field, which consists of a length header and a list of
202 * fixed64.
203 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
204 * @param {number} start Start of the data.
205 * @return {!Array<number>}
206 * @package
207 */
208function readPackedDouble(bufferDecoder, start) {
209  return readPacked(bufferDecoder, start, readDouble);
210}
211
212/**
213 * Reads a packed fixed32 field, which consists of a length header and a list of
214 * fixed32.
215 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
216 * @param {number} start Start of the data.
217 * @return {!Array<number>}
218 * @package
219 */
220function readPackedFixed32(bufferDecoder, start) {
221  return readPacked(bufferDecoder, start, readFixed32);
222}
223
224/**
225 * Reads a packed float field, which consists of a length header and a list of
226 * fixed64.
227 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
228 * @param {number} start Start of the data.
229 * @return {!Array<number>}
230 * @package
231 */
232function readPackedFloat(bufferDecoder, start) {
233  return readPacked(bufferDecoder, start, readFloat);
234}
235
236/**
237 * Reads a packed int32 field, which consists of a length header and a list of
238 * varint.
239 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
240 * @param {number} start Start of the data.
241 * @return {!Array<number>}
242 * @package
243 */
244function readPackedInt32(bufferDecoder, start) {
245  return readPacked(bufferDecoder, start, readInt32);
246}
247
248/**
249 * Reads a packed int64 field, which consists of a length header and a list
250 * of int64.
251 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
252 * @param {number} start Start of the data.
253 * @return {!Array<!Int64>}
254 * @package
255 */
256function readPackedInt64(bufferDecoder, start) {
257  return readPacked(bufferDecoder, start, readInt64);
258}
259
260/**
261 * Reads a packed sfixed32 field, which consists of a length header and a list
262 * of sfixed32.
263 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
264 * @param {number} start Start of the data.
265 * @return {!Array<number>}
266 * @package
267 */
268function readPackedSfixed32(bufferDecoder, start) {
269  return readPacked(bufferDecoder, start, readSfixed32);
270}
271
272/**
273 * Reads a packed sfixed64 field, which consists of a length header and a list
274 * of sfixed64.
275 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
276 * @param {number} start Start of the data.
277 * @return {!Array<!Int64>}
278 * @package
279 */
280function readPackedSfixed64(bufferDecoder, start) {
281  return readPacked(bufferDecoder, start, readSfixed64);
282}
283
284/**
285 * Reads a packed sint32 field, which consists of a length header and a list of
286 * varint.
287 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
288 * @param {number} start Start of the data.
289 * @return {!Array<number>}
290 * @package
291 */
292function readPackedSint32(bufferDecoder, start) {
293  return readPacked(bufferDecoder, start, readSint32);
294}
295
296/**
297 * Reads a packed sint64 field, which consists of a length header and a list
298 * of sint64.
299 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
300 * @param {number} start Start of the data.
301 * @return {!Array<!Int64>}
302 * @package
303 */
304function readPackedSint64(bufferDecoder, start) {
305  return readPacked(bufferDecoder, start, readSint64);
306}
307
308/**
309 * Reads a packed uint32 field, which consists of a length header and a list of
310 * varint.
311 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
312 * @param {number} start Start of the data.
313 * @return {!Array<number>}
314 * @package
315 */
316function readPackedUint32(bufferDecoder, start) {
317  return readPacked(bufferDecoder, start, readUint32);
318}
319
320/**
321 * Read packed values.
322 * @param {!BufferDecoder} bufferDecoder Binary format encoded bytes.
323 * @param {number} start Start of the data.
324 * @param {function(!BufferDecoder, number):T} valueFunction
325 * @return {!Array<T>}
326 * @package
327 * @template T
328 */
329function readPacked(bufferDecoder, start, valueFunction) {
330  const /** !Array<T> */ result = [];
331  const unsignedLength = bufferDecoder.getUnsignedVarint32At(start);
332  const dataStart = bufferDecoder.cursor();
333  while (bufferDecoder.cursor() < dataStart + unsignedLength) {
334    checkState(bufferDecoder.cursor() > 0);
335    result.push(valueFunction(bufferDecoder, bufferDecoder.cursor()));
336  }
337  return result;
338}
339
340exports = {
341  readBool,
342  readBytes,
343  readDelimited,
344  readDouble,
345  readFixed32,
346  readFloat,
347  readInt32,
348  readInt64,
349  readSint32,
350  readSint64,
351  readSfixed32,
352  readSfixed64,
353  readString,
354  readUint32,
355  readPackedBool,
356  readPackedDouble,
357  readPackedFixed32,
358  readPackedFloat,
359  readPackedInt32,
360  readPackedInt64,
361  readPackedSfixed32,
362  readPackedSfixed64,
363  readPackedSint32,
364  readPackedSint64,
365  readPackedUint32,
366};
367