@thi.ng/transducers-binary
Version:
Binary data related transducers & reducers
149 lines (148 loc) • 3.56 kB
JavaScript
import {
utf8Length as $utf8Length,
fromUtf8CodePoint
} from "@thi.ng/strings/utf8";
import { compR } from "@thi.ng/transducers/compr";
import { iterator, iterator1 } from "@thi.ng/transducers/iterator";
import { isReduced } from "@thi.ng/transducers/reduced";
function utf8Decode(src) {
return src ? [...iterator1(utf8Decode(), src)].join("") : (rfn) => {
const r = rfn[2];
let state = 0;
let u0;
let u1;
let u2;
let u3;
let u4;
return compR(rfn, (acc, x) => {
switch (state) {
case 0:
default:
if (x < 128) {
return r(acc, String.fromCharCode(x));
}
u0 = x;
state = 1;
break;
case 1:
u1 = x & 63;
if ((u0 & 224) === 192) {
state = 0;
return r(
acc,
String.fromCharCode((u0 & 31) << 6 | u1)
);
}
state = 2;
break;
case 2:
u2 = x & 63;
if ((u0 & 240) === 224) {
state = 0;
return r(
acc,
String.fromCharCode(
(u0 & 15) << 12 | u1 << 6 | u2
)
);
}
state = 3;
break;
case 3:
u3 = x & 63;
if ((u0 & 248) === 240) {
state = 0;
return r(
acc,
fromUtf8CodePoint(
(u0 & 7) << 18 | u1 << 12 | u2 << 6 | u3
)
);
}
state = 4;
break;
case 4:
u4 = x & 63;
if ((u0 & 252) === 248) {
state = 0;
return r(
acc,
fromUtf8CodePoint(
(u0 & 3) << 24 | u1 << 18 | u2 << 12 | u3 << 6 | u4
)
);
}
state = 5;
break;
case 5:
state = 0;
return r(
acc,
fromUtf8CodePoint(
(u0 & 1) << 30 | u1 << 24 | u2 << 18 | u3 << 12 | u4 << 6 | x & 63
)
);
}
return acc;
});
};
}
function utf8Encode(src) {
return src != null ? new Uint8Array(iterator(utf8Encode(), src)) : (rfn) => {
const r = rfn[2];
return compR(rfn, (acc, x) => {
let u = x.charCodeAt(0), buf;
if (u >= 55296 && u <= 57343) {
u = 65536 + ((u & 1023) << 10) | x.charCodeAt(1) & 1023;
}
if (u < 128) {
return r(acc, u);
} else if (u < 2048) {
buf = [192 | u >> 6, 128 | u & 63];
} else if (u < 65536) {
buf = [
224 | u >> 12,
128 | u >> 6 & 63,
128 | u & 63
];
} else if (u < 2097152) {
buf = [
240 | u >> 18,
128 | u >> 12 & 63,
128 | u >> 6 & 63,
128 | u & 63
];
} else if (u < 67108864) {
buf = [
248 | u >> 24,
128 | u >> 18 & 63,
128 | u >> 12 & 63,
128 | u >> 6 & 63,
128 | u & 63
];
} else {
buf = [
252 | u >> 30,
128 | u >> 24 & 63,
128 | u >> 18 & 63,
128 | u >> 12 & 63,
128 | u >> 6 & 63,
128 | u & 63
];
}
for (let i = 0, n = buf.length; i < n; i++) {
acc = r(acc, buf[i]);
if (isReduced(acc)) {
break;
}
}
return acc;
});
};
}
const utf8Length = $utf8Length;
export {
utf8Decode,
utf8Encode,
utf8Length
};