@observertc/samples-encoder
Version:
ObserveRTC Library for Encoding Samples
374 lines (297 loc) • 8.84 kB
text/typescript
const textEncoder = new TextEncoder();
// export interface Logger {
// info(...args: string[]): void;
// warn(...args: string[]): void;
// error(...args: string[]): void;
// }
// export class DefaultLogger implements Logger {
// info(...args: string[]) {
// console.info(...args);
// }
// warn(...args: string[]) {
// console.warn(...args);
// }
// error(...args: string[]) {
// console.error(...args);
// }
// }
export interface Encoder<I, O> {
actualValue?: I;
encode(newValue?: I): O | undefined;
reset(): void;
}
export interface AttachmentEncoder extends Encoder<Record<string, unknown>, string> {
reset(): void;
}
export type ClientSampleEncoderSettings = {
callIdIsUuid?: boolean;
clientIdIsUuid?: boolean;
peerConnectionIdIsUuid?: boolean;
trackIdIsUuid?: boolean;
};
export interface AttachmentsEncoderFactory {
createIceCandidatePairAttachmentEncoder(): AttachmentEncoder;
createCodecStatsAttachmentEncoder(): AttachmentEncoder;
createMediaSourceAttachmentEncoder(): AttachmentEncoder;
createMediaPlayoutAttachmentEncoder(): AttachmentEncoder;
createClientSampleAttachmentEncoder(): AttachmentEncoder;
createPeerConnectionSampleAttachmentEncoder(): AttachmentEncoder;
createCertificateAttachmentEncoder(): AttachmentEncoder;
createIceCandidateAttachmentEncoder(): AttachmentEncoder;
createIceTransportAttachmentEncoder(): AttachmentEncoder;
createInboundTrackAttachmentEncoder(): AttachmentEncoder;
createOutboundTrackAttachmentEncoder(): AttachmentEncoder;
createInboundRtpAttachmentEncoder(): AttachmentEncoder;
createOutboundRtpAttachmentEncoder(): AttachmentEncoder;
createDataChannelAttachmentEncoder(): AttachmentEncoder;
createRemoteInboundRtpAttachmentEncoder(): AttachmentEncoder;
createRemoteOutboundRtpAttachmentEncoder(): AttachmentEncoder;
createPeerConnectionTransportAttachmentEncoder(): AttachmentEncoder;
}
export class DefaultAttachmentEncoderFactory implements AttachmentsEncoderFactory {
public createIceCandidatePairAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createCodecStatsAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createClientSampleAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createInboundTrackAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createOutboundTrackAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createPeerConnectionSampleAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createCertificateAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createIceCandidateAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createIceTransportAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createInboundRtpAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createOutboundRtpAttachmentEncoder(): AttachmentEncoder {
return new DefaultAttachmentEncoder();
}
public createDataChannelAttachmentEncoder() {
return new DefaultAttachmentEncoder();
}
public createRemoteInboundRtpAttachmentEncoder() {
return new DefaultAttachmentEncoder();
}
public createRemoteOutboundRtpAttachmentEncoder() {
return new DefaultAttachmentEncoder();
}
public createMediaSourceAttachmentEncoder() {
return new DefaultAttachmentEncoder();
}
public createMediaPlayoutAttachmentEncoder() {
return new DefaultAttachmentEncoder();
}
public createPeerConnectionTransportAttachmentEncoder() {
return new DefaultAttachmentEncoder();
}
}
export class DefaultAttachmentEncoder implements AttachmentEncoder {
private _actualValueRef?: Record<string, unknown>;
public constructor() {
}
public reset() {
this._actualValueRef = undefined;
}
encode(newValue?: Record<string, unknown>) {
if (this._actualValueRef && newValue === this._actualValueRef) return;
if (newValue === undefined) return;
this._actualValueRef = newValue;
return JSON.stringify(newValue);
}
}
export class OneTimePassEncoder<T> implements Encoder<T, T> {
private _value: T | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: T) {
if (this._value !== undefined) return;
this._value = newValue;
return newValue;
}
}
export class OneTimePassUuidToByteArrayEncoder implements Encoder<string, Uint8Array> {
private _done?: boolean;
public reset() {
this._done = undefined;
}
encode(newValue?: string) {
if (newValue === undefined) return;
if (this._done) return;
this._done = true;
return uuidToByteArray(newValue);
}
}
export class OneTimePassStringToUint8ArrayEncoder implements Encoder<string, Uint8Array> {
private _done?: boolean;
public reset() {
this._done = undefined;
}
encode(newValue?: string) {
if (newValue === undefined) return;
if (this._done) return;
this._done = true;
return textEncoder.encode(newValue);
}
}
export class StringToStringEncoder implements Encoder<string, string> {
private _value: string | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: string) {
if (!newValue) return;
if (newValue === this._value) return;
this._value = newValue;
return newValue;
}
}
export class StringToUint8ArrayEncoder implements Encoder<string, Uint8Array> {
private _value: string | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: string) {
if (!newValue) return;
if (newValue === this._value) return;
this._value = newValue;
return textEncoder.encode(newValue);
}
}
export class StringToNumberEncoder implements Encoder<string, number> {
private _value: string | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: string) {
if (newValue === undefined) return;
if (newValue === this._value) return;
this._value = newValue;
return Number(newValue);
}
}
export class NumberToBigIntEncoder implements Encoder<number, bigint> {
private _value: number | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: number) {
if (newValue === undefined) return;
if (newValue === this._value) return;
this._value = newValue;
return BigInt(newValue);
}
}
export class NumberToNumberEncoder implements Encoder<number, number> {
private _value: number | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: number) {
if (newValue === undefined) return;
if (newValue === this._value) return;
this._value = newValue;
return newValue;
}
}
export class BooleanToBooleanEncoder implements Encoder<boolean, boolean> {
private _value: boolean | undefined;
public get actualValue() {
return this._value;
}
public reset() {
this._value = undefined;
}
encode(newValue?: boolean) {
if (!newValue) return;
if (newValue === this._value) return;
this._value = newValue;
return newValue;
}
}
export function stringToBytesArray(str: string): Uint8Array {
return textEncoder.encode(str);
}
export function uuidToByteArray(uuid: string): Uint8Array {
const hex = uuid.replace(/[-]/g, '');
const byteArray = new Uint8Array(16);
for (let i = 0, j = 0; i < 32; i += 2, j++) {
byteArray[j] = parseInt(hex.substr(i, 2), 16);
}
return byteArray;
}
/* Base64 string to array encoding */
function uint6ToB64(nUint6: number) {
return nUint6 < 26
? nUint6 + 65
: nUint6 < 52
? nUint6 + 71
: nUint6 < 62
? nUint6 - 4
: nUint6 === 62
? 43
: nUint6 === 63
? 47
: 65;
}
export function convertUint8ToBase64(aBytes: Uint8Array) {
let nMod3 = 2;
let sB64Enc = "";
const nLen = aBytes.length;
let nUint24 = 0;
for (let nIdx = 0; nIdx < nLen; nIdx++) {
nMod3 = nIdx % 3;
// To break your base64 into several 80-character lines, add:
// if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) {
// sB64Enc += "\r\n";
// }
nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24);
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
sB64Enc += String.fromCodePoint(
uint6ToB64((nUint24 >>> 18) & 63),
uint6ToB64((nUint24 >>> 12) & 63),
uint6ToB64((nUint24 >>> 6) & 63),
uint6ToB64(nUint24 & 63)
);
nUint24 = 0;
}
}
return (
sB64Enc.substring(0, sB64Enc.length - 2 + nMod3) +
(nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==")
);
}