2024-01-01 21:11:32 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2023-04-18 07:13:58 +00:00
|
|
|
|
|
|
|
export function runLengthEncode(arr: number[]) {
|
|
|
|
const data: number[] = [];
|
|
|
|
const runLengths: number[] = [];
|
|
|
|
|
|
|
|
let prev: symbol | number = Symbol("none");
|
|
|
|
|
|
|
|
for (const x of arr) {
|
|
|
|
if (x === prev) {
|
2024-07-03 22:12:41 +00:00
|
|
|
++runLengths[runLengths.length - 1]!;
|
2023-04-18 07:13:58 +00:00
|
|
|
} else {
|
|
|
|
prev = x;
|
|
|
|
data.push(x);
|
|
|
|
runLengths.push(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-05 21:20:21 +00:00
|
|
|
for (const r of runLengths) {
|
|
|
|
if (r >= 0x100) {
|
|
|
|
throw new Error(`Run length too long: ${r}`);
|
|
|
|
}
|
|
|
|
}
|
2023-04-18 07:13:58 +00:00
|
|
|
|
|
|
|
return {
|
|
|
|
d: btoa(String.fromCharCode(...data)),
|
|
|
|
r: btoa(String.fromCharCode(...runLengths)),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function runLengthDecode({ d, r }: { d: string; r: string }) {
|
|
|
|
const data = atob(d);
|
|
|
|
const runLengths = atob(r);
|
|
|
|
let out = "";
|
|
|
|
|
|
|
|
for (const [i, ch] of [...runLengths].entries()) {
|
2024-02-02 07:42:48 +00:00
|
|
|
out += data[i]!.repeat(ch.codePointAt(0)!);
|
2023-04-18 07:13:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return Uint8Array.from([...out].map((x) => x.codePointAt(0)!));
|
|
|
|
}
|