UNPKG

rtp.js

Version:

RTP stack for Node.js and browser written in TypeScript

231 lines (230 loc) 6.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clone = clone; exports.assertUnreachable = assertUnreachable; exports.padTo4Bytes = padTo4Bytes; exports.areDataViewsEqual = areDataViewsEqual; exports.nodeBufferToDataView = nodeBufferToDataView; exports.dataViewToNodeBuffer = dataViewToNodeBuffer; exports.nodeBufferToArrayBuffer = nodeBufferToArrayBuffer; exports.arrayBufferToNodeBuffer = arrayBufferToNodeBuffer; exports.numericArrayToDataView = numericArrayToDataView; exports.numberToDataView = numberToDataView; exports.dataViewToString = dataViewToString; exports.arrayBufferToString = arrayBufferToString; exports.stringToDataView = stringToDataView; exports.stringToArrayBuffer = stringToArrayBuffer; exports.stringToUint8Array = stringToUint8Array; exports.getStringByteLength = getStringByteLength; const Logger_1 = require("../Logger"); const logger = new Logger_1.Logger('utils/helpers'); /** * Clones the given object/array/Buffer/etc. * * @category Utils * @hidden */ function clone(data) { if (data instanceof ArrayBuffer || (typeof SharedArrayBuffer !== 'undefined' && data instanceof SharedArrayBuffer)) { return data.slice(0); } else if (data instanceof DataView) { return new DataView(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)); } else if (data === undefined) { return undefined; } else if (Number.isNaN(data)) { return NaN; } else if (typeof structuredClone === 'function') { // Available in Node >= 18. return structuredClone(data); } else { return JSON.parse(JSON.stringify(data)); } } /** * TypeScript utility to assert that no `case X` is missing in a `switch()` * block. * * @category Utils * @hidden */ function assertUnreachable(_x) { throw new Error(`we should not get here: ${_x}`); } /** * Returns the given size padded to 4 bytes. * * @category Utils */ function padTo4Bytes(size) { // If size is not multiple of 32 bits then pad it. if (size & 0x03) { return (size & 0xfffc) + 4; } else { return size; } } /** * Whether two DataViews contain the same data. * * @category Utils * @hidden */ function areDataViewsEqual(view1, view2) { if (view1 === view2) { logger.debug('areDataViewsEqual() | view1 and view2 are the same DataView instance'); return true; } if (view1.byteLength !== view2.byteLength) { if (logger.debug.enabled) { logger.debug(`areDataViewsEqual() | different byte length [view1.byteLength:${view1.byteLength}, view2.byteLength:${view2.byteLength}]`); logger.debug('areDataViewsEqual() | view1:', view1); logger.debug('areDataViewsEqual() | view2:', view2); } return false; } let i = 0; while (i < view1.byteLength) { if (view1.getUint8(i) !== view2.getUint8(i)) { if (logger.debug.enabled) { logger.debug(`areDataViewsEqual() | different byte [idx:${i}, view1:${view1 .getUint8(i) .toString(16)}, view2:${view2.getUint8(i).toString(16)}]`); logger.debug('areDataViewsEqual() | view1:', view1); logger.debug('areDataViewsEqual() | view2:', view2); } return false; } i++; } return true; } /** * Convert Node.js Buffer to DataView using the same underlying ArrayBuffer. * * @category Utils * @remarks * - Just for Node.js. */ function nodeBufferToDataView(nodeBuffer) { return new DataView(nodeBuffer.buffer, nodeBuffer.byteOffset, nodeBuffer.byteLength); } /** * Convert DataView to Node.js Buffer using the same underlying ArrayBuffer. * * @category Utils * @remarks * - Just for Node.js. */ function dataViewToNodeBuffer(view) { return Buffer.from(view.buffer, view.byteOffset, view.byteLength); } /** * Convert Node.js Buffer to a new allocated ArrayBufferLike. * * @category Utils * @remarks * - Just for Node.js. */ function nodeBufferToArrayBuffer(nodeBuffer) { return nodeBuffer.buffer.slice(nodeBuffer.byteOffset, nodeBuffer.byteOffset + nodeBuffer.byteLength); } /** * Convert ArrayBufferLike to Node.js Buffer. * * @category Utils * @remarks * - Just for Node.js. */ function arrayBufferToNodeBuffer(arrayBuffer) { return Buffer.from(arrayBuffer, 0, arrayBuffer.byteLength); } /** * Convert array of integers to DataView. * * @category Utils */ function numericArrayToDataView(array) { return new DataView(new Uint8Array(array).buffer); } /** * Convert number to DataView. * * @category Utils */ function numberToDataView(number) { const array = []; array.unshift(number & 255); while (number >= 256) { number = number >>> 8; array.unshift(number & 255); } const uint8Array = new Uint8Array(array); return new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength); } /** * Convert DataView to string. * * @category Utils */ function dataViewToString(view) { const decoder = new TextDecoder(); return decoder.decode(view); } /** * Convert ArrayBuffer to string. * * @category Utils */ function arrayBufferToString(arrayBuffer) { const decoder = new TextDecoder(); return decoder.decode(arrayBuffer); } /** * Convert string to DataView. * * @category Utils */ function stringToDataView(string) { const encoder = new TextEncoder(); const uint8Array = encoder.encode(string); return new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength); } /** * Convert string to ArrayBufferLike. * * @category Utils * @hidden */ function stringToArrayBuffer(string) { const encoder = new TextEncoder(); return encoder.encode(string).buffer; } /** * Convert string to Uint8Array. * * @category Utils * @hidden */ function stringToUint8Array(string) { const encoder = new TextEncoder(); const uint8Array = encoder.encode(string); return new Uint8Array(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength); } /** * Get the byte length of a string. * * @category Utils */ function getStringByteLength(string) { const encoder = new TextEncoder(); const uint8Array = encoder.encode(string); return uint8Array.byteLength; }