| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 | /** * @fileoverview Protobufs Int64 representation. */goog.module('protobuf.Int64');const Long = goog.require('goog.math.Long');const {assert} = goog.require('goog.asserts');/** * A container for protobufs Int64/Uint64 data type. * @final */class Int64 {  /** @return {!Int64} */  static getZero() {    return ZERO;  }  /** @return {!Int64} */  static getMinValue() {    return MIN_VALUE;  }  /** @return {!Int64} */  static getMaxValue() {    return MAX_VALUE;  }  /**   * Constructs a Int64 given two 32 bit numbers   * @param {number} lowBits   * @param {number} highBits   * @return {!Int64}   */  static fromBits(lowBits, highBits) {    return new Int64(lowBits, highBits);  }  /**   * Constructs an Int64 from a signed 32 bit number.   * @param {number} value   * @return {!Int64}   */  static fromInt(value) {    // TODO: Use our own checking system here.    assert(value === (value | 0), 'value should be a 32-bit integer');    // Right shift 31 bits so all high bits are equal to the sign bit.    // Note: cannot use >> 32, because (1 >> 32) = 1 (!).    const signExtendedHighBits = value >> 31;    return new Int64(value, signExtendedHighBits);  }  /**   * Constructs an Int64 from a number (over 32 bits).   * @param {number} value   * @return {!Int64}   */  static fromNumber(value) {    if (value > 0) {      return new Int64(value, value / TWO_PWR_32_DBL);    } else if (value < 0) {      return negate(-value, -value / TWO_PWR_32_DBL);    }    return ZERO;  }  /**   * Construct an Int64 from a signed decimal string.   * @param {string} value   * @return {!Int64}   */  static fromDecimalString(value) {    // TODO: Use our own checking system here.    assert(value.length > 0);    // The basic Number conversion loses precision, but we can use it for    // a quick validation that the format is correct and it is an integer.    assert(Math.floor(Number(value)).toString().length == value.length);    return decimalStringToInt64(value);  }  /**   * Construct an Int64 from a signed hexadecimal string.   * @param {string} value   * @return {!Int64}   */  static fromHexString(value) {    // TODO: Use our own checking system here.    assert(value.length > 0);    assert(value.slice(0, 2) == '0x' || value.slice(0, 3) == '-0x');    const minus = value[0] === '-';    // Strip the 0x or -0x prefix.    value = value.slice(minus ? 3 : 2);    const lowBits = parseInt(value.slice(-8), 16);    const highBits = parseInt(value.slice(-16, -8) || '', 16);    return (minus ? negate : Int64.fromBits)(lowBits, highBits);  }  // Note to the reader:  // goog.math.Long suffers from a code size issue. JsCompiler almost always  // considers toString methods to be alive in a program. So if you are  // constructing a Long instance the toString method is assumed to be live.  // Unfortunately Long's toString method makes a large chunk of code alive  // of the entire class adding 1.3kB (gzip) of extra code size.  // Callers that are sensitive to code size and are not using Long already  // should avoid calling this method.  /**   * Creates an Int64 instance from a Long value.   * @param {!Long} value   * @return {!Int64}   */  static fromLong(value) {    return new Int64(value.getLowBits(), value.getHighBits());  }  /**   * @param {number} lowBits   * @param {number} highBits   * @private   */  constructor(lowBits, highBits) {    /** @const @private {number} */    this.lowBits_ = lowBits | 0;    /** @const @private {number} */    this.highBits_ = highBits | 0;  }  /**   * Returns the int64 value as a JavaScript number. This will lose precision   * if the number is outside of the safe range for JavaScript of 53 bits   * precision.   * @return {number}   */  asNumber() {    const result = this.highBits_ * TWO_PWR_32_DBL + this.getLowBitsUnsigned();    // TODO: Use our own checking system here.    assert(        Number.isSafeInteger(result), 'conversion to number loses precision.');    return result;  }  // Note to the reader:  // goog.math.Long suffers from a code size issue. JsCompiler almost always  // considers toString methods to be alive in a program. So if you are  // constructing a Long instance the toString method is assumed to be live.  // Unfortunately Long's toString method makes a large chunk of code alive  // of the entire class adding 1.3kB (gzip) of extra code size.  // Callers that are sensitive to code size and are not using Long already  // should avoid calling this method.  /** @return {!Long} */  asLong() {    return Long.fromBits(this.lowBits_, this.highBits_);  }  /** @return {number} Signed 32-bit integer value. */  getLowBits() {    return this.lowBits_;  }  /** @return {number} Signed 32-bit integer value. */  getHighBits() {    return this.highBits_;  }  /** @return {number} Unsigned 32-bit integer. */  getLowBitsUnsigned() {    return this.lowBits_ >>> 0;  }  /** @return {number} Unsigned 32-bit integer. */  getHighBitsUnsigned() {    return this.highBits_ >>> 0;  }  /** @return {string} */  toSignedDecimalString() {    return joinSignedDecimalString(this);  }  /** @return {string} */  toUnsignedDecimalString() {    return joinUnsignedDecimalString(this);  }  /**   * Returns an unsigned hexadecimal string representation of the Int64.   * @return {string}   */  toHexString() {    let nibbles = new Array(16);    let lowBits = this.lowBits_;    let highBits = this.highBits_;    for (let highIndex = 7, lowIndex = 15; lowIndex > 7;         highIndex--, lowIndex--) {      nibbles[highIndex] = HEX_DIGITS[highBits & 0xF];      nibbles[lowIndex] = HEX_DIGITS[lowBits & 0xF];      highBits = highBits >>> 4;      lowBits = lowBits >>> 4;    }    // Always leave the least significant hex digit.    while (nibbles.length > 1 && nibbles[0] == '0') {      nibbles.shift();    }    return `0x${nibbles.join('')}`;  }  /**   * @param {*} other object to compare against.   * @return {boolean} Whether this Int64 equals the other.   */  equals(other) {    if (this === other) {      return true;    }    if (!(other instanceof Int64)) {      return false;    }    // Compare low parts first as there is higher chance they are different.    const otherInt64 = /** @type{!Int64} */ (other);    return (this.lowBits_ === otherInt64.lowBits_) &&        (this.highBits_ === otherInt64.highBits_);  }  /**   * Returns a number (int32) that is suitable for using in hashed structures.   * @return {number}   */  hashCode() {    return (31 * this.lowBits_ + 17 * this.highBits_) | 0;  }}/** * Losslessly converts a 64-bit unsigned integer in 32:32 split representation * into a decimal string. * @param {!Int64} int64 * @return {string} The binary number represented as a string. */const joinUnsignedDecimalString = (int64) => {  const lowBits = int64.getLowBitsUnsigned();  const highBits = int64.getHighBitsUnsigned();  // Skip the expensive conversion if the number is small enough to use the  // built-in conversions.  // Number.MAX_SAFE_INTEGER = 0x001FFFFF FFFFFFFF, thus any number with  // highBits <= 0x1FFFFF can be safely expressed with a double and retain  // integer precision.  // Proven by: Number.isSafeInteger(0x1FFFFF * 2**32 + 0xFFFFFFFF) == true.  if (highBits <= 0x1FFFFF) {    return String(TWO_PWR_32_DBL * highBits + lowBits);  }  // What this code is doing is essentially converting the input number from  // base-2 to base-1e7, which allows us to represent the 64-bit range with  // only 3 (very large) digits. Those digits are then trivial to convert to  // a base-10 string.  // The magic numbers used here are -  // 2^24 = 16777216 = (1,6777216) in base-1e7.  // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7.  // Split 32:32 representation into 16:24:24 representation so our  // intermediate digits don't overflow.  const low = lowBits & LOW_24_BITS;  const mid = ((lowBits >>> 24) | (highBits << 8)) & LOW_24_BITS;  const high = (highBits >> 16) & LOW_16_BITS;  // Assemble our three base-1e7 digits, ignoring carries. The maximum  // value in a digit at this step is representable as a 48-bit integer, which  // can be stored in a 64-bit floating point number.  let digitA = low + (mid * 6777216) + (high * 6710656);  let digitB = mid + (high * 8147497);  let digitC = (high * 2);  // Apply carries from A to B and from B to C.  const base = 10000000;  if (digitA >= base) {    digitB += Math.floor(digitA / base);    digitA %= base;  }  if (digitB >= base) {    digitC += Math.floor(digitB / base);    digitB %= base;  }  // If digitC is 0, then we should have returned in the trivial code path  // at the top for non-safe integers. Given this, we can assume both digitB  // and digitA need leading zeros.  // TODO: Use our own checking system here.  assert(digitC);  return digitC + decimalFrom1e7WithLeadingZeros(digitB) +      decimalFrom1e7WithLeadingZeros(digitA);};/** * @param {number} digit1e7 Number < 1e7 * @return {string} Decimal representation of digit1e7 with leading zeros. */const decimalFrom1e7WithLeadingZeros = (digit1e7) => {  const partial = String(digit1e7);  return '0000000'.slice(partial.length) + partial;};/** * Losslessly converts a 64-bit signed integer in 32:32 split representation * into a decimal string. * @param {!Int64} int64 * @return {string} The binary number represented as a string. */const joinSignedDecimalString = (int64) => {  // If we're treating the input as a signed value and the high bit is set, do  // a manual two's complement conversion before the decimal conversion.  const negative = (int64.getHighBits() & 0x80000000);  if (negative) {    int64 = negate(int64.getLowBits(), int64.getHighBits());  }  const result = joinUnsignedDecimalString(int64);  return negative ? '-' + result : result;};/** * @param {string} dec * @return {!Int64} */const decimalStringToInt64 = (dec) => {  // Check for minus sign.  const minus = dec[0] === '-';  if (minus) {    dec = dec.slice(1);  }  // Work 6 decimal digits at a time, acting like we're converting base 1e6  // digits to binary. This is safe to do with floating point math because  // Number.isSafeInteger(ALL_32_BITS * 1e6) == true.  const base = 1e6;  let lowBits = 0;  let highBits = 0;  function add1e6digit(begin, end = undefined) {    // Note: Number('') is 0.    const digit1e6 = Number(dec.slice(begin, end));    highBits *= base;    lowBits = lowBits * base + digit1e6;    // Carry bits from lowBits to    if (lowBits >= TWO_PWR_32_DBL) {      highBits = highBits + ((lowBits / TWO_PWR_32_DBL) | 0);      lowBits = lowBits % TWO_PWR_32_DBL;    }  }  add1e6digit(-24, -18);  add1e6digit(-18, -12);  add1e6digit(-12, -6);  add1e6digit(-6);  return (minus ? negate : Int64.fromBits)(lowBits, highBits);};/** * @param {number} lowBits * @param {number} highBits * @return {!Int64} Two's compliment negation of input. * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Signed_32-bit_integers */const negate = (lowBits, highBits) => {  highBits = ~highBits;  if (lowBits) {    lowBits = ~lowBits + 1;  } else {    // If lowBits is 0, then bitwise-not is 0xFFFFFFFF,    // adding 1 to that, results in 0x100000000, which leaves    // the low bits 0x0 and simply adds one to the high bits.    highBits += 1;  }  return Int64.fromBits(lowBits, highBits);};/** @const {!Int64} */const ZERO = new Int64(0, 0);/** @const @private {number} */const LOW_16_BITS = 0xFFFF;/** @const @private {number} */const LOW_24_BITS = 0xFFFFFF;/** @const @private {number} */const LOW_31_BITS = 0x7FFFFFFF;/** @const @private {number} */const ALL_32_BITS = 0xFFFFFFFF;/** @const {!Int64} */const MAX_VALUE = Int64.fromBits(ALL_32_BITS, LOW_31_BITS);/** @const {!Int64} */const MIN_VALUE = Int64.fromBits(0, 0x80000000);/** @const {number} */const TWO_PWR_32_DBL = 0x100000000;/** @const {string} */const HEX_DIGITS = '0123456789abcdef';exports = Int64;
 |