| /** |
| * @fileoverview Provides ByteString as a basic data type for protos. |
| */ |
| goog.module('protobuf.ByteString'); |
| |
| const base64 = goog.require('goog.crypt.base64'); |
| const {arrayBufferSlice, cloneArrayBufferView, hashUint8Array, uint8ArrayEqual} = goog.require('protobuf.binary.typedArrays'); |
| |
| /** |
| * Immutable sequence of bytes. |
| * |
| * Bytes can be obtained as an ArrayBuffer or a base64 encoded string. |
| * @final |
| */ |
| class ByteString { |
| /** |
| * @param {?Uint8Array} bytes |
| * @param {?string} base64 |
| * @private |
| */ |
| constructor(bytes, base64) { |
| /** @private {?Uint8Array}*/ |
| this.bytes_ = bytes; |
| /** @private {?string} */ |
| this.base64_ = base64; |
| /** @private {number} */ |
| this.hashCode_ = 0; |
| } |
| |
| /** |
| * Constructs a ByteString instance from a base64 string. |
| * @param {string} value |
| * @return {!ByteString} |
| */ |
| static fromBase64String(value) { |
| if (value == null) { |
| throw new Error('value must not be null'); |
| } |
| return new ByteString(/* bytes */ null, value); |
| } |
| |
| /** |
| * Constructs a ByteString from an array buffer. |
| * @param {!ArrayBuffer} bytes |
| * @param {number=} start |
| * @param {number=} end |
| * @return {!ByteString} |
| */ |
| static fromArrayBuffer(bytes, start = 0, end = undefined) { |
| return new ByteString( |
| new Uint8Array(arrayBufferSlice(bytes, start, end)), /* base64 */ null); |
| } |
| |
| /** |
| * Constructs a ByteString from any ArrayBufferView (e.g. DataView, |
| * TypedArray, Uint8Array, etc.). |
| * @param {!ArrayBufferView} bytes |
| * @return {!ByteString} |
| */ |
| static fromArrayBufferView(bytes) { |
| return new ByteString(cloneArrayBufferView(bytes), /* base64 */ null); |
| } |
| |
| /** |
| * Constructs a ByteString from an Uint8Array. DON'T MODIFY the underlying |
| * ArrayBuffer, since the ByteString directly uses it without making a copy. |
| * |
| * This method exists so that internal APIs can construct a ByteString without |
| * paying the penalty of copying an ArrayBuffer when that ArrayBuffer is not |
| * supposed to change. It is exposed to a limited number of internal classes |
| * through bytestring_internal.js. |
| * |
| * @param {!Uint8Array} bytes |
| * @return {!ByteString} |
| * @package |
| */ |
| static fromUint8ArrayUnsafe(bytes) { |
| return new ByteString(bytes, /* base64 */ null); |
| } |
| |
| /** |
| * Returns this ByteString as an ArrayBuffer. |
| * @return {!ArrayBuffer} |
| */ |
| toArrayBuffer() { |
| const bytes = this.ensureBytes_(); |
| return arrayBufferSlice( |
| bytes.buffer, bytes.byteOffset, bytes.byteOffset + bytes.byteLength); |
| } |
| |
| /** |
| * Returns this ByteString as an Uint8Array. DON'T MODIFY the returned array, |
| * since the ByteString holds the reference to the same array. |
| * |
| * This method exists so that internal APIs can get contents of a ByteString |
| * without paying the penalty of copying an ArrayBuffer. It is exposed to a |
| * limited number of internal classes through bytestring_internal.js. |
| * @return {!Uint8Array} |
| * @package |
| */ |
| toUint8ArrayUnsafe() { |
| return this.ensureBytes_(); |
| } |
| |
| /** |
| * Returns this ByteString as a base64 encoded string. |
| * @return {string} |
| */ |
| toBase64String() { |
| return this.ensureBase64String_(); |
| } |
| |
| /** |
| * Returns true for Bytestrings that contain identical values. |
| * @param {*} other |
| * @return {boolean} |
| */ |
| equals(other) { |
| if (this === other) { |
| return true; |
| } |
| |
| if (!(other instanceof ByteString)) { |
| return false; |
| } |
| |
| const otherByteString = /** @type {!ByteString} */ (other); |
| return uint8ArrayEqual(this.ensureBytes_(), otherByteString.ensureBytes_()); |
| } |
| |
| /** |
| * Returns a number (int32) that is suitable for using in hashed structures. |
| * @return {number} |
| */ |
| hashCode() { |
| if (this.hashCode_ == 0) { |
| this.hashCode_ = hashUint8Array(this.ensureBytes_()); |
| } |
| return this.hashCode_; |
| } |
| |
| /** |
| * Returns true if the bytestring is empty. |
| * @return {boolean} |
| */ |
| isEmpty() { |
| if (this.bytes_ != null && this.bytes_.byteLength == 0) { |
| return true; |
| } |
| if (this.base64_ != null && this.base64_.length == 0) { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * @return {!Uint8Array} |
| * @private |
| */ |
| ensureBytes_() { |
| if (this.bytes_) { |
| return this.bytes_; |
| } |
| return this.bytes_ = base64.decodeStringToUint8Array( |
| /** @type {string} */ (this.base64_)); |
| } |
| |
| /** |
| * @return {string} |
| * @private |
| */ |
| ensureBase64String_() { |
| if (this.base64_ == null) { |
| this.base64_ = base64.encodeByteArray(this.bytes_); |
| } |
| return this.base64_; |
| } |
| } |
| |
| /** @const {!ByteString} */ |
| ByteString.EMPTY = new ByteString(new Uint8Array(0), null); |
| |
| exports = ByteString; |