UNPKG

@thi.ng/transducers-binary

Version:

Binary data related transducers & reducers

149 lines (148 loc) 3.56 kB
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 };