UNPKG

@thi.ng/transducers-binary

Version:

Binary data related transducers & reducers

104 lines (103 loc) 2.63 kB
import { compR } from "@thi.ng/transducers/compr"; import { __iter, iterator, iterator1 } from "@thi.ng/transducers/iterator"; import { isReduced, reduced } from "@thi.ng/transducers/reduced"; const B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const B64_SAFE = B64_CHARS.substring(0, 62) + "-_"; function base64Decode(src) { return src ? new Uint8Array(iterator1(base64Decode(), src)) : (rfn) => { const r = rfn[2]; let bc = 0, bs = 0; return compR(rfn, (acc, x) => { switch (x) { case "-": x = "+"; break; case "_": x = "/"; break; case "=": return reduced(acc); default: } const y = B64_CHARS.indexOf(x); bs = bc & 3 ? (bs << 6) + y : y; if (bc++ & 3) { acc = r(acc, 255 & bs >> (-2 * bc & 6)); } return acc; }); }; } function base64Encode(...args) { const iter = __iter(base64Encode, args, iterator); if (iter) { return [...iter].join(""); } return ([init, complete, reduce]) => { let state = 0; let b; const opts = { safe: false, buffer: 1024, ...args[0] }; const chars = opts.safe ? B64_SAFE : B64_CHARS; const buf = []; return [ init, (acc) => { switch (state) { case 1: buf.push( chars[b >> 18 & 63], chars[b >> 12 & 63], "=", "=" ); break; case 2: buf.push( chars[b >> 18 & 63], chars[b >> 12 & 63], chars[b >> 6 & 63], "=" ); break; default: } while (buf.length && !isReduced(acc)) { acc = reduce(acc, buf.shift()); } return complete(acc); }, (acc, x) => { switch (state) { case 0: state = 1; b = x << 16; break; case 1: state = 2; b += x << 8; break; default: state = 0; b += x; buf.push( chars[b >> 18 & 63], chars[b >> 12 & 63], chars[b >> 6 & 63], chars[b & 63] ); if (buf.length >= opts.buffer) { for (let i = 0, n = buf.length; i < n && !isReduced(acc); i++) { acc = reduce(acc, buf[i]); } buf.length = 0; } } return acc; } ]; }; } export { base64Decode, base64Encode };