rtp.js
Version:
RTP stack for Node.js and browser written in TypeScript
231 lines (230 loc) • 6.39 kB
JavaScript
;
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;
}