| /** |
| * @fileoverview Internal utilities for working with buffers. |
| * @package |
| * |
| * DO NOT USE THIS OUTSIDE OF THIS PACKAGE. |
| */ |
| goog.module('jspb.binary.internal_buffer'); |
| |
| const {ByteSource} = goog.require('jspb.binary.bytesource'); |
| const {ByteString} = goog.require('jspb.bytestring'); |
| const {decodeByteArray} = goog.require('jspb.internal_bytes'); |
| const {unsafeByteStringFromUint8Array, unsafeUint8ArrayFromByteString} = goog.require('jspb.unsafe_bytestring'); |
| |
| |
| class Buffer { |
| constructor(/** !Uint8Array */ buffer, /** boolean */ isImmutable, |
| /** !ByteString= */ maybeByteString) { |
| /** @const {!Uint8Array}*/ |
| this.buffer = buffer; |
| |
| /** @private {!ByteString|undefined} */ |
| this.bufferAsByteStringInternal = maybeByteString; |
| if (maybeByteString && !isImmutable) { |
| throw goog.DEBUG ? |
| new Error('Buffer must be immutable if a ByteString is provided.') : |
| new Error(); |
| } |
| |
| /** |
| * Whether our input must be immutable and we cannot allow callers to |
| * mutate it. |
| * |
| * @const {boolean} |
| */ |
| this.isImmutable = isImmutable; |
| } |
| |
| /** @return {?ByteString} */ |
| getBufferAsByteStringIfImmutable() { |
| if (!this.isImmutable) { |
| throw goog.DEBUG ? |
| new Error('Cannot get ByteString from mutable buffer.') : |
| new Error(); |
| } |
| if (this.buffer == null) return null; |
| return this.bufferAsByteStringInternal ??= |
| unsafeByteStringFromUint8Array(this.buffer); |
| } |
| } |
| |
| /** |
| * Converts any type defined in ByteSource into a Uint8Array. |
| * @param {!ByteSource|!ByteString} data |
| * @param {boolean} treatNewDataAsImmutable Whether to treat new data as |
| * immutable. |
| * @return {!Buffer} a tuple of the data and |
| * whether or not this is an immutable reference |
| */ |
| function bufferFromSource(data, treatNewDataAsImmutable) { |
| if (typeof data === 'string') { |
| return new Buffer(decodeByteArray(data), treatNewDataAsImmutable); |
| } else if (Array.isArray(data)) { |
| return new Buffer(new Uint8Array(data), treatNewDataAsImmutable); |
| } else if (data.constructor === Uint8Array) { |
| const u8 = /** @type {!Uint8Array}*/ (data); |
| return new Buffer(u8, /* isImmutable= */ false); |
| } else if (data.constructor === ArrayBuffer) { |
| const u8 = new Uint8Array(/** @type {!ArrayBuffer} */ (data)); |
| return new Buffer(u8, /* isImmutable= */ false); |
| } else if (data.constructor === ByteString) { |
| const byteString = /** @type {!ByteString} */ (data); |
| const u8 = unsafeUint8ArrayFromByteString(byteString); |
| return new Buffer(u8, /* isImmutable= */ true, byteString); |
| } else if (data instanceof Uint8Array) { |
| // If this is a node subclass, wrap a new Uint8Array around the buffer to |
| // ensure jspb code only ever deals with Uint8Array exactly to ensure |
| // monomorphism. |
| const u8 = (data.constructor === Uint8Array) ? |
| data : |
| new Uint8Array(data.buffer, data.byteOffset, data.byteLength); |
| return new Buffer(u8, /* isImmutable= */ false); |
| } else { |
| throw goog.DEBUG ? |
| new Error( |
| 'Type not convertible to a Uint8Array, expected a Uint8Array, an ' + |
| 'ArrayBuffer, a base64 encoded string, a ByteString or an Array of ' + |
| 'numbers') : |
| new Error(); |
| } |
| } |
| |
| |
| exports = { |
| Buffer, |
| bufferFromSource, |
| }; |