Browse Source

Extract shared codec logic into higher order function

codec
Luke Childs 8 years ago
parent
commit
0e77205c59
  1. 68
      src/index.js

68
src/index.js

@ -1,17 +1,5 @@
'use strict';
const validateOpts = (opts, chunkMultiple) => {
opts = Object.assign({}, { chunkSize: 10000 }, opts);
opts.chunkSize = Math.ceil(opts.chunkSize / chunkMultiple) * chunkMultiple;
if (opts.chunkSize === 0) {
throw new Error('opts.chunkSize must be larger than 0');
}
return opts;
};
const b64 = (input, opts) => {
if (input instanceof Buffer || typeof input === 'string') {
const method = input instanceof Buffer ? 'encode' : 'decode';
@ -21,21 +9,26 @@ const b64 = (input, opts) => {
return Promise.reject(new TypeError('input must be a buffer or string'));
};
b64.encode = (input, opts) => new Promise(resolve => {
const chunkMultiple = 3;
opts = validateOpts(opts, chunkMultiple);
const createCodec = codecOpts => (input, opts) => new Promise(resolve => {
const { chunkMultiple, inputTypeCheck, initialOutput, updateOutput } = codecOpts;
if (!(input instanceof Buffer)) {
throw new TypeError('input must be a buffer');
opts = Object.assign({}, { chunkSize: 10000 }, opts);
opts.chunkSize = Math.ceil(opts.chunkSize / chunkMultiple) * chunkMultiple;
if (opts.chunkSize === 0) {
throw new Error('opts.chunkSize must be larger than 0');
}
inputTypeCheck(input);
const bufferLength = input.length;
let currentIndex = 0;
let output = '';
let output = initialOutput;
setImmediate(function encodeChunk() {
const chunk = input.slice(currentIndex, currentIndex + opts.chunkSize);
output += chunk.toString('base64');
output = updateOutput(output, chunk);
currentIndex += opts.chunkSize;
if (currentIndex < bufferLength) {
setImmediate(encodeChunk);
@ -45,28 +38,29 @@ b64.encode = (input, opts) => new Promise(resolve => {
});
});
b64.decode = (input, opts) => new Promise(resolve => {
const chunkMultiple = 4;
opts = validateOpts(opts, chunkMultiple);
b64.encode = createCodec({
chunkMultiple: 3,
inputTypeCheck: input => {
if (!(input instanceof Buffer)) {
throw new TypeError('input must be a buffer');
}
},
initialOutput: '',
updateOutput: (output, chunk) => {
output += chunk.toString('base64');
return output;
}
});
b64.decode = createCodec({
chunkMultiple: 4,
inputTypeCheck: input => {
if (typeof input !== 'string') {
throw new TypeError('input must be a base64 string');
}
const stringLength = input.length;
let currentIndex = 0;
let output = Buffer.alloc(0);
setImmediate(function encodeChunk() {
const chunk = input.slice(currentIndex, currentIndex + opts.chunkSize);
output = Buffer.concat([output, Buffer.from(chunk, 'base64')]);
currentIndex += opts.chunkSize;
if (currentIndex < stringLength) {
setImmediate(encodeChunk);
} else {
resolve(output);
}
});
},
initialOutput: Buffer.alloc(0),
updateOutput: (output, chunk) => Buffer.concat([output, Buffer.from(chunk, 'base64')])
});
module.exports = b64;

Loading…
Cancel
Save