decoder.js 31 KB

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