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