Skip to content

Commit

Permalink
feat(rle-pack): add support for custom input word sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Aug 9, 2018
1 parent 4fdd3c9 commit fd8e761
Showing 1 changed file with 35 additions and 21 deletions.
56 changes: 35 additions & 21 deletions packages/rle-pack/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,67 @@ import { BitInputStream, BitOutputStream } from "@thi.ng/bitstream";

const RLE_SIZES = [3, 4, 8, 16];

export function encodeBytes(src: Uint8Array) {
const stream = new BitOutputStream().write(src.length, 32);
let num = src.length - 1;
let val = src[0];
/**
* Compresses input using dynamically sized RLE compression and returns
* result as `Uint8Array`.
*
* @param src
* @param num number of input words
* @param wordSize in bits, MUST be <= 8
*/
export function encodeBytes(src: Iterable<number>, num: number, wordSize = 8) {
const stream = new BitOutputStream(num * wordSize / 8).write(num, 32);
const n1 = num - 1;
let val;
let tail = true;
let n = -1;
let x, i, t;
let i = 0, t;
const write = () => {
stream.write(n > 0 ? 1 : 0, 1);
stream.write(val, 8);
stream.write(val, wordSize);
if (n > 0) {
t = (n < 0x8) ? 0 : (n < 0x10) ? 1 : (n < 0x100) ? 2 : 3;
stream.write(t, 2);
stream.write(n, RLE_SIZES[t]);
}
n = 0;
};
for (i = 0; i <= num; i++) {
x = src[i];
if (x !== val) {
for (let x of src) {
if (val === undefined) {
val = x;
} else if (x !== val) {
write();
val = x;
} else {
if (++n === 0x10000) {
write();
tail = (i < num);
tail = (i < n1);
}
}
i++;
}
if (tail) {
write();
}
if (tail) { write(); }
return stream.bytes();
}

export function decodeBytes(src: Uint8Array) {
let num = (src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]);
let input = new BitInputStream(src, 32);
let out = new Uint8Array(num);
let i = 0;
export function decodeBytes(src: Uint8Array, wordSize = 8) {
const input = new BitInputStream(src);
const ws1 = wordSize + 1;
const num = input.read(32);
const out = new Uint8Array(num);
const flag = 1 << wordSize;
const mask = flag - 1;
let x, j;
while (i < num) {
x = input.read(9);
if (x & 0x100) {
for (let i = 0; i < num;) {
x = input.read(ws1);
if (x & flag) {
j = i + 1 + input.read(RLE_SIZES[input.read(2)]);
out.fill(x & 0xff, i, j);
out.fill(x & mask, i, j);
i = j;
} else {
out[i++] = x & 0xff;
out[i++] = x & mask;
}
}
return out;
Expand Down

0 comments on commit fd8e761

Please sign in to comment.