Skip to content

Commit e07c1d8

Browse files
committed
Add array compression function.
1 parent fb56f65 commit e07c1d8

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

packages/p2p-media-loader-core/src/core.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { BandwidthApproximator } from "./bandwidth-approximator";
1313
import { EngineCallbacks } from "./request-container";
1414
import { SegmentsMemoryStorage } from "./segments-storage";
1515
import * as Bits from "./p2p/bits";
16-
import { serializeNumbersArray } from "./p2p/bits";
1716

1817
export class Core<TStream extends Stream = Stream> {
1918
private manifestResponseUrl?: string;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { PeerCommandType } from "../enums";
2+
3+
export function integerToBytesArray(num: number): number[] {
4+
const bytesAmount = requiredBytesForInteger(num);
5+
const bytes: number[] = [];
6+
7+
for (let i = 0; i < bytesAmount; i++) {
8+
bytes[i] = (num >> (8 * i)) & 0xff;
9+
}
10+
return bytes;
11+
}
12+
13+
export function bytesArrayToInteger(bytes: Uint8Array): number {
14+
let number = 0;
15+
for (let i = 0; i < bytes.length; i++) {
16+
const byte = bytes[i];
17+
number += byte << (8 * i);
18+
}
19+
20+
return number;
21+
}
22+
23+
function requiredBytesForInteger(num: number) {
24+
num = Math.abs(num);
25+
const bits = Math.floor(Math.log2(num)) + 1;
26+
return Math.ceil(bits / 8);
27+
}
28+
29+
// restricted to max 8 item types (3 bits to type definition)
30+
enum SerializedItem {
31+
Number,
32+
NumberArray,
33+
}
34+
35+
export function serializeNumber(num: number) {
36+
const numBytes = integerToBytesArray(num);
37+
// 5 bits for
38+
const numberMetadata = (SerializedItem.Number << 5) | numBytes.length;
39+
return new Uint8Array([numberMetadata, ...numBytes]);
40+
}
41+
42+
export function deserializeNumber(bytes: Uint8Array, position: number) {
43+
const metadata = bytes[position];
44+
const code = (metadata & 0b11100000) >> 5;
45+
if (code !== SerializedItem.Number) {
46+
throw new Error("error");
47+
}
48+
const numberBytesLength = metadata & 0b00011111;
49+
const start = position + 1;
50+
const end = start + numberBytesLength;
51+
return {
52+
number: bytesArrayToInteger(bytes.slice(start, end)),
53+
byteLength: numberBytesLength + 1,
54+
};
55+
}
56+
57+
function serializeArray(numbers: number[]) {
58+
const maxBytes = getMaxForArray(numbers, (num) =>
59+
requiredBytesForInteger(num)
60+
);
61+
62+
let common = numbers[0];
63+
for (let i = 1; i < numbers.length; i++) {
64+
common &= numbers[i];
65+
}
66+
const diffMask = ~common;
67+
const diff = numbers.map((num) => num & diffMask);
68+
}
69+
70+
function getCommandBytes() {
71+
const bytes: number[] = [
72+
"{".charCodeAt(0),
73+
PeerCommandType.CancelSegmentRequest,
74+
...serializeNumber(65411),
75+
"}".charCodeAt(0),
76+
];
77+
}
78+
79+
function getMaxForArray<T>(arr: T[], getValue: (item: T) => number): number {
80+
let max = Number.MIN_VALUE;
81+
for (const item of arr) {
82+
const value = getValue(item);
83+
if (value > max) max = value;
84+
}
85+
86+
return max;
87+
}

0 commit comments

Comments
 (0)