decoder.js 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. /**
  31. * @fileoverview This file contains utilities for decoding primitive values
  32. * (signed and unsigned integers, varints, booleans, enums, hashes, strings,
  33. * and raw bytes) embedded in Uint8Arrays into their corresponding Javascript
  34. * types.
  35. *
  36. * Major caveat - Javascript is unable to accurately represent integers larger
  37. * than 2^53 due to its use of a double-precision floating point format or all
  38. * numbers. If you need to guarantee that 64-bit values survive with all bits
  39. * intact, you _must_ read them using one of the Hash64 methods, which return
  40. * an 8-character string.
  41. *
  42. * @author aappleby@google.com (Austin Appleby)
  43. */
  44. goog.provide('jspb.BinaryDecoder');
  45. goog.provide('jspb.BinaryIterator');
  46. goog.require('goog.asserts');
  47. goog.require('goog.crypt');
  48. goog.require('jspb.utils');
  49. /**
  50. * Simple helper class for traversing the contents of repeated scalar fields.
  51. * that may or may not have been packed into a wire-format blob.
  52. * @param {?jspb.BinaryDecoder=} opt_decoder
  53. * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
  54. * opt_next The decoder method to use for next().
  55. * @param {?Array<number|boolean|string>=} opt_elements
  56. * @constructor
  57. * @struct
  58. */
  59. jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) {
  60. /** @private {?jspb.BinaryDecoder} */
  61. this.decoder_ = null;
  62. /**
  63. * The BinaryDecoder member function used when iterating over packed data.
  64. * @private {?function(this:jspb.BinaryDecoder):(number|boolean|string)}
  65. */
  66. this.nextMethod_ = null;
  67. /** @private {?Array<number|boolean|string>} */
  68. this.elements_ = null;
  69. /** @private {number} */
  70. this.cursor_ = 0;
  71. /** @private {number|boolean|string|null} */
  72. this.nextValue_ = null;
  73. /** @private {boolean} */
  74. this.atEnd_ = true;
  75. this.init_(opt_decoder, opt_next, opt_elements);
  76. };
  77. /**
  78. * @param {?jspb.BinaryDecoder=} opt_decoder
  79. * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
  80. * opt_next The decoder method to use for next().
  81. * @param {?Array<number|boolean|string>=} opt_elements
  82. * @private
  83. */
  84. jspb.BinaryIterator.prototype.init_ =
  85. function(opt_decoder, opt_next, opt_elements) {
  86. if (opt_decoder && opt_next) {
  87. this.decoder_ = opt_decoder;
  88. this.nextMethod_ = opt_next;
  89. }
  90. this.elements_ = opt_elements || null;
  91. this.cursor_ = 0;
  92. this.nextValue_ = null;
  93. this.atEnd_ = !this.decoder_ && !this.elements_;
  94. this.next();
  95. };
  96. /**
  97. * Global pool of BinaryIterator instances.
  98. * @private {!Array<!jspb.BinaryIterator>}
  99. */
  100. jspb.BinaryIterator.instanceCache_ = [];
  101. /**
  102. * Allocates a BinaryIterator from the cache, creating a new one if the cache
  103. * is empty.
  104. * @param {?jspb.BinaryDecoder=} opt_decoder
  105. * @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
  106. * opt_next The decoder method to use for next().
  107. * @param {?Array<number|boolean|string>=} opt_elements
  108. * @return {!jspb.BinaryIterator}
  109. */
  110. jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) {
  111. if (jspb.BinaryIterator.instanceCache_.length) {
  112. var iterator = jspb.BinaryIterator.instanceCache_.pop();
  113. iterator.init_(opt_decoder, opt_next, opt_elements);
  114. return iterator;
  115. } else {
  116. return new jspb.BinaryIterator(opt_decoder, opt_next, opt_elements);
  117. }
  118. };
  119. /**
  120. * Puts this instance back in the instance cache.
  121. */
  122. jspb.BinaryIterator.prototype.free = function() {
  123. this.clear();
  124. if (jspb.BinaryIterator.instanceCache_.length < 100) {
  125. jspb.BinaryIterator.instanceCache_.push(this);
  126. }
  127. };
  128. /**
  129. * Clears the iterator.
  130. */
  131. jspb.BinaryIterator.prototype.clear = function() {
  132. if (this.decoder_) {
  133. this.decoder_.free();
  134. }
  135. this.decoder_ = null;
  136. this.nextMethod_ = null;
  137. this.elements_ = null;
  138. this.cursor_ = 0;
  139. this.nextValue_ = null;
  140. this.atEnd_ = true;
  141. };
  142. /**
  143. * Returns the element at the iterator, or null if the iterator is invalid or
  144. * past the end of the decoder/array.
  145. * @return {number|boolean|string|null}
  146. */
  147. jspb.BinaryIterator.prototype.get = function() {
  148. return this.nextValue_;
  149. };
  150. /**
  151. * Returns true if the iterator is at the end of the decoder/array.
  152. * @return {boolean}
  153. */
  154. jspb.BinaryIterator.prototype.atEnd = function() {
  155. return this.atEnd_;
  156. };
  157. /**
  158. * Returns the element at the iterator and steps to the next element,
  159. * equivalent to '*pointer++' in C.
  160. * @return {number|boolean|string|null}
  161. */
  162. jspb.BinaryIterator.prototype.next = function() {
  163. var lastValue = this.nextValue_;
  164. if (this.decoder_) {
  165. if (this.decoder_.atEnd()) {
  166. this.nextValue_ = null;
  167. this.atEnd_ = true;
  168. } else {
  169. this.nextValue_ = this.nextMethod_.call(this.decoder_);
  170. }
  171. } else if (this.elements_) {
  172. if (this.cursor_ == this.elements_.length) {
  173. this.nextValue_ = null;
  174. this.atEnd_ = true;
  175. } else {
  176. this.nextValue_ = this.elements_[this.cursor_++];
  177. }
  178. }
  179. return lastValue;
  180. };
  181. /**
  182. * BinaryDecoder implements the decoders for all the wire types specified in
  183. * https://developers.google.com/protocol-buffers/docs/encoding.
  184. *
  185. * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
  186. * @param {number=} opt_start The optional offset to start reading at.
  187. * @param {number=} opt_length The optional length of the block to read -
  188. * we'll throw an assertion if we go off the end of the block.
  189. * @constructor
  190. * @struct
  191. */
  192. jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) {
  193. /**
  194. * Typed byte-wise view of the source buffer.
  195. * @private {?Uint8Array}
  196. */
  197. this.bytes_ = null;
  198. /**
  199. * Start point of the block to read.
  200. * @private {number}
  201. */
  202. this.start_ = 0;
  203. /**
  204. * End point of the block to read.
  205. * @private {number}
  206. */
  207. this.end_ = 0;
  208. /**
  209. * Current read location in bytes_.
  210. * @private {number}
  211. */
  212. this.cursor_ = 0;
  213. /**
  214. * Set to true if this decoder encountered an error due to corrupt data.
  215. * @private {boolean}
  216. */
  217. this.error_ = false;
  218. if (opt_bytes) {
  219. this.setBlock(opt_bytes, opt_start, opt_length);
  220. }
  221. };
  222. /**
  223. * Global pool of BinaryDecoder instances.
  224. * @private {!Array<!jspb.BinaryDecoder>}
  225. */
  226. jspb.BinaryDecoder.instanceCache_ = [];
  227. /**
  228. * Pops an instance off the instance cache, or creates one if the cache is
  229. * empty.
  230. * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
  231. * @param {number=} opt_start The optional offset to start reading at.
  232. * @param {number=} opt_length The optional length of the block to read -
  233. * we'll throw an assertion if we go off the end of the block.
  234. * @return {!jspb.BinaryDecoder}
  235. */
  236. jspb.BinaryDecoder.alloc = function(opt_bytes, opt_start, opt_length) {
  237. if (jspb.BinaryDecoder.instanceCache_.length) {
  238. var newDecoder = jspb.BinaryDecoder.instanceCache_.pop();
  239. if (opt_bytes) {
  240. newDecoder.setBlock(opt_bytes, opt_start, opt_length);
  241. }
  242. return newDecoder;
  243. } else {
  244. return new jspb.BinaryDecoder(opt_bytes, opt_start, opt_length);
  245. }
  246. };
  247. /**
  248. * Puts this instance back in the instance cache.
  249. */
  250. jspb.BinaryDecoder.prototype.free = function() {
  251. this.clear();
  252. if (jspb.BinaryDecoder.instanceCache_.length < 100) {
  253. jspb.BinaryDecoder.instanceCache_.push(this);
  254. }
  255. };
  256. /**
  257. * Makes a copy of this decoder.
  258. * @return {!jspb.BinaryDecoder}
  259. */
  260. jspb.BinaryDecoder.prototype.clone = function() {
  261. return jspb.BinaryDecoder.alloc(this.bytes_,
  262. this.start_, this.end_ - this.start_);
  263. };
  264. /**
  265. * Clears the decoder.
  266. */
  267. jspb.BinaryDecoder.prototype.clear = function() {
  268. this.bytes_ = null;
  269. this.start_ = 0;
  270. this.end_ = 0;
  271. this.cursor_ = 0;
  272. this.error_ = false;
  273. };
  274. /**
  275. * Returns the raw buffer.
  276. * @return {?Uint8Array} The raw buffer.
  277. */
  278. jspb.BinaryDecoder.prototype.getBuffer = function() {
  279. return this.bytes_;
  280. };
  281. /**
  282. * Changes the block of bytes we're decoding.
  283. * @param {!jspb.ByteSource} data The bytes we're reading from.
  284. * @param {number=} opt_start The optional offset to start reading at.
  285. * @param {number=} opt_length The optional length of the block to read -
  286. * we'll throw an assertion if we go off the end of the block.
  287. */
  288. jspb.BinaryDecoder.prototype.setBlock =
  289. function(data, opt_start, opt_length) {
  290. this.bytes_ = jspb.utils.byteSourceToUint8Array(data);
  291. this.start_ = goog.isDef(opt_start) ? opt_start : 0;
  292. this.end_ =
  293. goog.isDef(opt_length) ? this.start_ + opt_length : this.bytes_.length;
  294. this.cursor_ = this.start_;
  295. };
  296. /**
  297. * @return {number}
  298. */
  299. jspb.BinaryDecoder.prototype.getEnd = function() {
  300. return this.end_;
  301. };
  302. /**
  303. * @param {number} end
  304. */
  305. jspb.BinaryDecoder.prototype.setEnd = function(end) {
  306. this.end_ = end;
  307. };
  308. /**
  309. * Moves the read cursor back to the start of the block.
  310. */
  311. jspb.BinaryDecoder.prototype.reset = function() {
  312. this.cursor_ = this.start_;
  313. };
  314. /**
  315. * Returns the internal read cursor.
  316. * @return {number} The internal read cursor.
  317. */
  318. jspb.BinaryDecoder.prototype.getCursor = function() {
  319. return this.cursor_;
  320. };
  321. /**
  322. * Returns the internal read cursor.
  323. * @param {number} cursor The new cursor.
  324. */
  325. jspb.BinaryDecoder.prototype.setCursor = function(cursor) {
  326. this.cursor_ = cursor;
  327. };
  328. /**
  329. * Advances the stream cursor by the given number of bytes.
  330. * @param {number} count The number of bytes to advance by.
  331. */
  332. jspb.BinaryDecoder.prototype.advance = function(count) {
  333. this.cursor_ += count;
  334. goog.asserts.assert(this.cursor_ <= this.end_);
  335. };
  336. /**
  337. * Returns true if this decoder is at the end of the block.
  338. * @return {boolean}
  339. */
  340. jspb.BinaryDecoder.prototype.atEnd = function() {
  341. return this.cursor_ == this.end_;
  342. };
  343. /**
  344. * Returns true if this decoder is at the end of the block.
  345. * @return {boolean}
  346. */
  347. jspb.BinaryDecoder.prototype.pastEnd = function() {
  348. return this.cursor_ > this.end_;
  349. };
  350. /**
  351. * Returns true if this decoder encountered an error due to corrupt data.
  352. * @return {boolean}
  353. */
  354. jspb.BinaryDecoder.prototype.getError = function() {
  355. return this.error_ ||
  356. (this.cursor_ < 0) ||
  357. (this.cursor_ > this.end_);
  358. };
  359. /**
  360. * Reads an unsigned varint from the binary stream and invokes the conversion
  361. * function with the value in two signed 32 bit integers to produce the result.
  362. * Since this does not convert the value to a number, no precision is lost.
  363. *
  364. * It's possible for an unsigned varint to be incorrectly encoded - more than
  365. * 64 bits' worth of data could be present. If this happens, this method will
  366. * throw an error.
  367. *
  368. * Decoding varints requires doing some funny base-128 math - for more
  369. * details on the format, see
  370. * https://developers.google.com/protocol-buffers/docs/encoding
  371. *
  372. * @param {function(number, number): T} convert Conversion function to produce
  373. * the result value, takes parameters (lowBits, highBits).
  374. * @return {T}
  375. * @template T
  376. */
  377. jspb.BinaryDecoder.prototype.readSplitVarint64 = function(convert) {
  378. var temp = 128;
  379. var lowBits = 0;
  380. var highBits = 0;
  381. // Read the first four bytes of the varint, stopping at the terminator if we
  382. // see it.
  383. for (var i = 0; i < 4 && temp >= 128; i++) {
  384. temp = this.bytes_[this.cursor_++];
  385. lowBits |= (temp & 0x7F) << (i * 7);
  386. }
  387. if (temp >= 128) {
  388. // Read the fifth byte, which straddles the low and high dwords.
  389. temp = this.bytes_[this.cursor_++];
  390. lowBits |= (temp & 0x7F) << 28;
  391. highBits |= (temp & 0x7F) >> 4;
  392. }
  393. if (temp >= 128) {
  394. // Read the sixth through tenth byte.
  395. for (var i = 0; i < 5 && temp >= 128; i++) {
  396. temp = this.bytes_[this.cursor_++];
  397. highBits |= (temp & 0x7F) << (i * 7 + 3);
  398. }
  399. }
  400. if (temp < 128) {
  401. return convert(lowBits >>> 0, highBits >>> 0);
  402. }
  403. // If we did not see the terminator, the encoding was invalid.
  404. goog.asserts.fail('Failed to read varint, encoding is invalid.');
  405. this.error_ = true;
  406. };
  407. /**
  408. * Reads a 64-bit fixed-width value from the stream and invokes the conversion
  409. * function with the value in two signed 32 bit integers to produce the result.
  410. * Since this does not convert the value to a number, no precision is lost.
  411. *
  412. * @param {function(number, number): T} convert Conversion function to produce
  413. * the result value, takes parameters (lowBits, highBits).
  414. * @return {T}
  415. * @template T
  416. */
  417. jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) {
  418. var bytes = this.bytes_;
  419. var cursor = this.cursor_;
  420. this.cursor_ += 8;
  421. var lowBits = 0;
  422. var highBits = 0;
  423. for (var i = cursor + 7; i >= cursor; i--) {
  424. lowBits = (lowBits << 8) | bytes[i];
  425. highBits = (highBits << 8) | bytes[i + 4];
  426. }
  427. return convert(lowBits, highBits);
  428. };
  429. /**
  430. * Skips over a varint in the block without decoding it.
  431. */
  432. jspb.BinaryDecoder.prototype.skipVarint = function() {
  433. while (this.bytes_[this.cursor_] & 0x80) {
  434. this.cursor_++;
  435. }
  436. this.cursor_++;
  437. };
  438. /**
  439. * Skips backwards over a varint in the block - to do this correctly, we have
  440. * to know the value we're skipping backwards over or things are ambiguous.
  441. * @param {number} value The varint value to unskip.
  442. */
  443. jspb.BinaryDecoder.prototype.unskipVarint = function(value) {
  444. while (value > 128) {
  445. this.cursor_--;
  446. value = value >>> 7;
  447. }
  448. this.cursor_--;
  449. };
  450. /**
  451. * Reads a 32-bit varint from the binary stream. Due to a quirk of the encoding
  452. * format and Javascript's handling of bitwise math, this actually works
  453. * correctly for both signed and unsigned 32-bit varints.
  454. *
  455. * This function is called vastly more frequently than any other in
  456. * BinaryDecoder, so it has been unrolled and tweaked for performance.
  457. *
  458. * If there are more than 32 bits of data in the varint, it _must_ be due to
  459. * sign-extension. If we're in debug mode and the high 32 bits don't match the
  460. * expected sign extension, this method will throw an error.
  461. *
  462. * Decoding varints requires doing some funny base-128 math - for more
  463. * details on the format, see
  464. * https://developers.google.com/protocol-buffers/docs/encoding
  465. *
  466. * @return {number} The decoded unsigned 32-bit varint.
  467. */
  468. jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() {
  469. var temp;
  470. var bytes = this.bytes_;
  471. temp = bytes[this.cursor_ + 0];
  472. var x = (temp & 0x7F);
  473. if (temp < 128) {
  474. this.cursor_ += 1;
  475. goog.asserts.assert(this.cursor_ <= this.end_);
  476. return x;
  477. }
  478. temp = bytes[this.cursor_ + 1];
  479. x |= (temp & 0x7F) << 7;
  480. if (temp < 128) {
  481. this.cursor_ += 2;
  482. goog.asserts.assert(this.cursor_ <= this.end_);
  483. return x;
  484. }
  485. temp = bytes[this.cursor_ + 2];
  486. x |= (temp & 0x7F) << 14;
  487. if (temp < 128) {
  488. this.cursor_ += 3;
  489. goog.asserts.assert(this.cursor_ <= this.end_);
  490. return x;
  491. }
  492. temp = bytes[this.cursor_ + 3];
  493. x |= (temp & 0x7F) << 21;
  494. if (temp < 128) {
  495. this.cursor_ += 4;
  496. goog.asserts.assert(this.cursor_ <= this.end_);
  497. return x;
  498. }
  499. temp = bytes[this.cursor_ + 4];
  500. x |= (temp & 0x0F) << 28;
  501. if (temp < 128) {
  502. // We're reading the high bits of an unsigned varint. The byte we just read
  503. // also contains bits 33 through 35, which we're going to discard.
  504. this.cursor_ += 5;
  505. goog.asserts.assert(this.cursor_ <= this.end_);
  506. return x >>> 0;
  507. }
  508. // If we get here, we need to truncate coming bytes. However we need to make
  509. // sure cursor place is correct.
  510. this.cursor_ += 5;
  511. if (bytes[this.cursor_++] >= 128 &&
  512. bytes[this.cursor_++] >= 128 &&
  513. bytes[this.cursor_++] >= 128 &&
  514. bytes[this.cursor_++] >= 128 &&
  515. bytes[this.cursor_++] >= 128) {
  516. // If we get here, the varint is too long.
  517. goog.asserts.assert(false);
  518. }
  519. goog.asserts.assert(this.cursor_ <= this.end_);
  520. return x;
  521. };
  522. /**
  523. * The readUnsignedVarint32 above deals with signed 32-bit varints correctly,
  524. * so this is just an alias.
  525. *
  526. * @return {number} The decoded signed 32-bit varint.
  527. */
  528. jspb.BinaryDecoder.prototype.readSignedVarint32 =
  529. jspb.BinaryDecoder.prototype.readUnsignedVarint32;
  530. /**
  531. * Reads a 32-bit unsigned variant and returns its value as a string.
  532. *
  533. * @return {string} The decoded unsigned 32-bit varint as a string.
  534. */
  535. jspb.BinaryDecoder.prototype.readUnsignedVarint32String = function() {
  536. // 32-bit integers fit in JavaScript numbers without loss of precision, so
  537. // string variants of 32-bit varint readers can simply delegate then convert
  538. // to string.
  539. var value = this.readUnsignedVarint32();
  540. return value.toString();
  541. };
  542. /**
  543. * Reads a 32-bit signed variant and returns its value as a string.
  544. *
  545. * @return {string} The decoded signed 32-bit varint as a string.
  546. */
  547. jspb.BinaryDecoder.prototype.readSignedVarint32String = function() {
  548. // 32-bit integers fit in JavaScript numbers without loss of precision, so
  549. // string variants of 32-bit varint readers can simply delegate then convert
  550. // to string.
  551. var value = this.readSignedVarint32();
  552. return value.toString();
  553. };
  554. /**
  555. * Reads a signed, zigzag-encoded 32-bit varint from the binary stream.
  556. *
  557. * Zigzag encoding is a modification of varint encoding that reduces the
  558. * storage overhead for small negative integers - for more details on the
  559. * format, see https://developers.google.com/protocol-buffers/docs/encoding
  560. *
  561. * @return {number} The decoded signed, zigzag-encoded 32-bit varint.
  562. */
  563. jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() {
  564. var result = this.readUnsignedVarint32();
  565. return (result >>> 1) ^ - (result & 1);
  566. };
  567. /**
  568. * Reads an unsigned 64-bit varint from the binary stream. Note that since
  569. * Javascript represents all numbers as double-precision floats, there will be
  570. * precision lost if the absolute value of the varint is larger than 2^53.
  571. *
  572. * @return {number} The decoded unsigned varint. Precision will be lost if the
  573. * integer exceeds 2^53.
  574. */
  575. jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() {
  576. return this.readSplitVarint64(jspb.utils.joinUint64);
  577. };
  578. /**
  579. * Reads an unsigned 64-bit varint from the binary stream and returns the value
  580. * as a decimal string.
  581. *
  582. * @return {string} The decoded unsigned varint as a decimal string.
  583. */
  584. jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() {
  585. return this.readSplitVarint64(jspb.utils.joinUnsignedDecimalString);
  586. };
  587. /**
  588. * Reads a signed 64-bit varint from the binary stream. Note that since
  589. * Javascript represents all numbers as double-precision floats, there will be
  590. * precision lost if the absolute value of the varint is larger than 2^53.
  591. *
  592. * @return {number} The decoded signed varint. Precision will be lost if the
  593. * integer exceeds 2^53.
  594. */
  595. jspb.BinaryDecoder.prototype.readSignedVarint64 = function() {
  596. return this.readSplitVarint64(jspb.utils.joinInt64);
  597. };
  598. /**
  599. * Reads an signed 64-bit varint from the binary stream and returns the value
  600. * as a decimal string.
  601. *
  602. * @return {string} The decoded signed varint as a decimal string.
  603. */
  604. jspb.BinaryDecoder.prototype.readSignedVarint64String = function() {
  605. return this.readSplitVarint64(jspb.utils.joinSignedDecimalString);
  606. };
  607. /**
  608. * Reads a signed, zigzag-encoded 64-bit varint from the binary stream. Note
  609. * that since Javascript represents all numbers as double-precision floats,
  610. * there will be precision lost if the absolute value of the varint is larger
  611. * than 2^53.
  612. *
  613. * Zigzag encoding is a modification of varint encoding that reduces the
  614. * storage overhead for small negative integers - for more details on the
  615. * format, see https://developers.google.com/protocol-buffers/docs/encoding
  616. *
  617. * @return {number} The decoded zigzag varint. Precision will be lost if the
  618. * integer exceeds 2^53.
  619. */
  620. jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {
  621. return this.readSplitVarint64(jspb.utils.joinZigzag64);
  622. };
  623. /**
  624. * Reads a signed, zigzag-encoded 64-bit varint from the binary stream and
  625. * returns its valud as a string.
  626. *
  627. * Zigzag encoding is a modification of varint encoding that reduces the
  628. * storage overhead for small negative integers - for more details on the
  629. * format, see https://developers.google.com/protocol-buffers/docs/encoding
  630. *
  631. * @return {string} The decoded signed, zigzag-encoded 64-bit varint as a
  632. * string.
  633. */
  634. jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() {
  635. // TODO(haberman): write lossless 64-bit zig-zag math.
  636. var value = this.readZigzagVarint64();
  637. return value.toString();
  638. };
  639. /**
  640. * Reads a raw unsigned 8-bit integer from the binary stream.
  641. *
  642. * @return {number} The unsigned 8-bit integer read from the binary stream.
  643. */
  644. jspb.BinaryDecoder.prototype.readUint8 = function() {
  645. var a = this.bytes_[this.cursor_ + 0];
  646. this.cursor_ += 1;
  647. goog.asserts.assert(this.cursor_ <= this.end_);
  648. return a;
  649. };
  650. /**
  651. * Reads a raw unsigned 16-bit integer from the binary stream.
  652. *
  653. * @return {number} The unsigned 16-bit integer read from the binary stream.
  654. */
  655. jspb.BinaryDecoder.prototype.readUint16 = function() {
  656. var a = this.bytes_[this.cursor_ + 0];
  657. var b = this.bytes_[this.cursor_ + 1];
  658. this.cursor_ += 2;
  659. goog.asserts.assert(this.cursor_ <= this.end_);
  660. return (a << 0) | (b << 8);
  661. };
  662. /**
  663. * Reads a raw unsigned 32-bit integer from the binary stream.
  664. *
  665. * @return {number} The unsigned 32-bit integer read from the binary stream.
  666. */
  667. jspb.BinaryDecoder.prototype.readUint32 = function() {
  668. var a = this.bytes_[this.cursor_ + 0];
  669. var b = this.bytes_[this.cursor_ + 1];
  670. var c = this.bytes_[this.cursor_ + 2];
  671. var d = this.bytes_[this.cursor_ + 3];
  672. this.cursor_ += 4;
  673. goog.asserts.assert(this.cursor_ <= this.end_);
  674. return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0;
  675. };
  676. /**
  677. * Reads a raw unsigned 64-bit integer from the binary stream. Note that since
  678. * Javascript represents all numbers as double-precision floats, there will be
  679. * precision lost if the absolute value of the integer is larger than 2^53.
  680. *
  681. * @return {number} The unsigned 64-bit integer read from the binary stream.
  682. * Precision will be lost if the integer exceeds 2^53.
  683. */
  684. jspb.BinaryDecoder.prototype.readUint64 = function() {
  685. var bitsLow = this.readUint32();
  686. var bitsHigh = this.readUint32();
  687. return jspb.utils.joinUint64(bitsLow, bitsHigh);
  688. };
  689. /**
  690. * Reads a raw unsigned 64-bit integer from the binary stream. Note that since
  691. * Javascript represents all numbers as double-precision floats, there will be
  692. * precision lost if the absolute value of the integer is larger than 2^53.
  693. *
  694. * @return {string} The unsigned 64-bit integer read from the binary stream.
  695. */
  696. jspb.BinaryDecoder.prototype.readUint64String = function() {
  697. var bitsLow = this.readUint32();
  698. var bitsHigh = this.readUint32();
  699. return jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh);
  700. };
  701. /**
  702. * Reads a raw signed 8-bit integer from the binary stream.
  703. *
  704. * @return {number} The signed 8-bit integer read from the binary stream.
  705. */
  706. jspb.BinaryDecoder.prototype.readInt8 = function() {
  707. var a = this.bytes_[this.cursor_ + 0];
  708. this.cursor_ += 1;
  709. goog.asserts.assert(this.cursor_ <= this.end_);
  710. return (a << 24) >> 24;
  711. };
  712. /**
  713. * Reads a raw signed 16-bit integer from the binary stream.
  714. *
  715. * @return {number} The signed 16-bit integer read from the binary stream.
  716. */
  717. jspb.BinaryDecoder.prototype.readInt16 = function() {
  718. var a = this.bytes_[this.cursor_ + 0];
  719. var b = this.bytes_[this.cursor_ + 1];
  720. this.cursor_ += 2;
  721. goog.asserts.assert(this.cursor_ <= this.end_);
  722. return (((a << 0) | (b << 8)) << 16) >> 16;
  723. };
  724. /**
  725. * Reads a raw signed 32-bit integer from the binary stream.
  726. *
  727. * @return {number} The signed 32-bit integer read from the binary stream.
  728. */
  729. jspb.BinaryDecoder.prototype.readInt32 = function() {
  730. var a = this.bytes_[this.cursor_ + 0];
  731. var b = this.bytes_[this.cursor_ + 1];
  732. var c = this.bytes_[this.cursor_ + 2];
  733. var d = this.bytes_[this.cursor_ + 3];
  734. this.cursor_ += 4;
  735. goog.asserts.assert(this.cursor_ <= this.end_);
  736. return (a << 0) | (b << 8) | (c << 16) | (d << 24);
  737. };
  738. /**
  739. * Reads a raw signed 64-bit integer from the binary stream. Note that since
  740. * Javascript represents all numbers as double-precision floats, there will be
  741. * precision lost if the absolute vlaue of the integer is larger than 2^53.
  742. *
  743. * @return {number} The signed 64-bit integer read from the binary stream.
  744. * Precision will be lost if the integer exceeds 2^53.
  745. */
  746. jspb.BinaryDecoder.prototype.readInt64 = function() {
  747. var bitsLow = this.readUint32();
  748. var bitsHigh = this.readUint32();
  749. return jspb.utils.joinInt64(bitsLow, bitsHigh);
  750. };
  751. /**
  752. * Reads a raw signed 64-bit integer from the binary stream and returns it as a
  753. * string.
  754. *
  755. * @return {string} The signed 64-bit integer read from the binary stream.
  756. * Precision will be lost if the integer exceeds 2^53.
  757. */
  758. jspb.BinaryDecoder.prototype.readInt64String = function() {
  759. var bitsLow = this.readUint32();
  760. var bitsHigh = this.readUint32();
  761. return jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh);
  762. };
  763. /**
  764. * Reads a 32-bit floating-point number from the binary stream, using the
  765. * temporary buffer to realign the data.
  766. *
  767. * @return {number} The float read from the binary stream.
  768. */
  769. jspb.BinaryDecoder.prototype.readFloat = function() {
  770. var bitsLow = this.readUint32();
  771. var bitsHigh = 0;
  772. return jspb.utils.joinFloat32(bitsLow, bitsHigh);
  773. };
  774. /**
  775. * Reads a 64-bit floating-point number from the binary stream, using the
  776. * temporary buffer to realign the data.
  777. *
  778. * @return {number} The double read from the binary stream.
  779. */
  780. jspb.BinaryDecoder.prototype.readDouble = function() {
  781. var bitsLow = this.readUint32();
  782. var bitsHigh = this.readUint32();
  783. return jspb.utils.joinFloat64(bitsLow, bitsHigh);
  784. };
  785. /**
  786. * Reads a boolean value from the binary stream.
  787. * @return {boolean} The boolean read from the binary stream.
  788. */
  789. jspb.BinaryDecoder.prototype.readBool = function() {
  790. return !!this.bytes_[this.cursor_++];
  791. };
  792. /**
  793. * Reads an enum value from the binary stream, which are always encoded as
  794. * signed varints.
  795. * @return {number} The enum value read from the binary stream.
  796. */
  797. jspb.BinaryDecoder.prototype.readEnum = function() {
  798. return this.readSignedVarint32();
  799. };
  800. /**
  801. * Reads and parses a UTF-8 encoded unicode string from the stream.
  802. * The code is inspired by maps.vectortown.parse.StreamedDataViewReader.
  803. * Supports codepoints from U+0000 up to U+10FFFF.
  804. * (http://en.wikipedia.org/wiki/UTF-8).
  805. * @param {number} length The length of the string to read.
  806. * @return {string} The decoded string.
  807. */
  808. jspb.BinaryDecoder.prototype.readString = function(length) {
  809. var bytes = this.bytes_;
  810. var cursor = this.cursor_;
  811. var end = cursor + length;
  812. var codeUnits = [];
  813. var result = '';
  814. while (cursor < end) {
  815. var c = bytes[cursor++];
  816. if (c < 128) { // Regular 7-bit ASCII.
  817. codeUnits.push(c);
  818. } else if (c < 192) {
  819. // UTF-8 continuation mark. We are out of sync. This
  820. // might happen if we attempted to read a character
  821. // with more than four bytes.
  822. continue;
  823. } else if (c < 224) { // UTF-8 with two bytes.
  824. var c2 = bytes[cursor++];
  825. codeUnits.push(((c & 31) << 6) | (c2 & 63));
  826. } else if (c < 240) { // UTF-8 with three bytes.
  827. var c2 = bytes[cursor++];
  828. var c3 = bytes[cursor++];
  829. codeUnits.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  830. } else if (c < 248) { // UTF-8 with 4 bytes.
  831. var c2 = bytes[cursor++];
  832. var c3 = bytes[cursor++];
  833. var c4 = bytes[cursor++];
  834. // Characters written on 4 bytes have 21 bits for a codepoint.
  835. // We can't fit that on 16bit characters, so we use surrogates.
  836. var codepoint = ((c & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63);
  837. // Surrogates formula from wikipedia.
  838. // 1. Subtract 0x10000 from codepoint
  839. codepoint -= 0x10000;
  840. // 2. Split this into the high 10-bit value and the low 10-bit value
  841. // 3. Add 0xD800 to the high value to form the high surrogate
  842. // 4. Add 0xDC00 to the low value to form the low surrogate:
  843. var low = (codepoint & 1023) + 0xDC00;
  844. var high = ((codepoint >> 10) & 1023) + 0xD800;
  845. codeUnits.push(high, low);
  846. }
  847. // Avoid exceeding the maximum stack size when calling `apply`.
  848. if (codeUnits.length >= 8192) {
  849. result += String.fromCharCode.apply(null, codeUnits);
  850. codeUnits.length = 0;
  851. }
  852. }
  853. result += goog.crypt.byteArrayToString(codeUnits);
  854. this.cursor_ = cursor;
  855. return result;
  856. };
  857. /**
  858. * Reads and parses a UTF-8 encoded unicode string (with length prefix) from
  859. * the stream.
  860. * @return {string} The decoded string.
  861. */
  862. jspb.BinaryDecoder.prototype.readStringWithLength = function() {
  863. var length = this.readUnsignedVarint32();
  864. return this.readString(length);
  865. };
  866. /**
  867. * Reads a block of raw bytes from the binary stream.
  868. *
  869. * @param {number} length The number of bytes to read.
  870. * @return {!Uint8Array} The decoded block of bytes, or an empty block if the
  871. * length was invalid.
  872. */
  873. jspb.BinaryDecoder.prototype.readBytes = function(length) {
  874. if (length < 0 ||
  875. this.cursor_ + length > this.bytes_.length) {
  876. this.error_ = true;
  877. goog.asserts.fail('Invalid byte length!');
  878. return new Uint8Array(0);
  879. }
  880. var result = this.bytes_.subarray(this.cursor_, this.cursor_ + length);
  881. this.cursor_ += length;
  882. goog.asserts.assert(this.cursor_ <= this.end_);
  883. return result;
  884. };
  885. /**
  886. * Reads a 64-bit varint from the stream and returns it as an 8-character
  887. * Unicode string for use as a hash table key.
  888. *
  889. * @return {string} The hash value.
  890. */
  891. jspb.BinaryDecoder.prototype.readVarintHash64 = function() {
  892. return this.readSplitVarint64(jspb.utils.joinHash64);
  893. };
  894. /**
  895. * Reads a 64-bit fixed-width value from the stream and returns it as an
  896. * 8-character Unicode string for use as a hash table key.
  897. *
  898. * @return {string} The hash value.
  899. */
  900. jspb.BinaryDecoder.prototype.readFixedHash64 = function() {
  901. var bytes = this.bytes_;
  902. var cursor = this.cursor_;
  903. var a = bytes[cursor + 0];
  904. var b = bytes[cursor + 1];
  905. var c = bytes[cursor + 2];
  906. var d = bytes[cursor + 3];
  907. var e = bytes[cursor + 4];
  908. var f = bytes[cursor + 5];
  909. var g = bytes[cursor + 6];
  910. var h = bytes[cursor + 7];
  911. this.cursor_ += 8;
  912. return String.fromCharCode(a, b, c, d, e, f, g, h);
  913. };