2017-10-14 20:24:18 +00:00
|
|
|
/*jslint es6: true, for: true, bitwise: true*/
|
2017-10-13 22:30:57 +00:00
|
|
|
/*global window*/
|
|
|
|
(function () {
|
|
|
|
"use strict";
|
|
|
|
|
2017-10-14 20:24:18 +00:00
|
|
|
const {btoa, atob} = window;
|
2017-10-13 22:30:57 +00:00
|
|
|
const bucketSize = 8;
|
|
|
|
|
2017-10-14 04:23:49 +00:00
|
|
|
const bufferToBase64 = function (buf) {
|
|
|
|
const binstr = Array.prototype.map.call(buf, function (ch) {
|
|
|
|
return String.fromCharCode(ch);
|
|
|
|
}).join('');
|
|
|
|
return btoa(binstr);
|
|
|
|
};
|
|
|
|
|
|
|
|
const base64ToBuffer = function (base64) {
|
|
|
|
const binstr = atob(base64);
|
|
|
|
const buf = new Uint8Array(binstr.length);
|
|
|
|
Array.prototype.forEach.call(binstr, function (ch, i) {
|
2017-10-14 20:24:18 +00:00
|
|
|
buf[i] = ch.charCodeAt(0);
|
2017-10-14 04:23:49 +00:00
|
|
|
});
|
|
|
|
return buf;
|
|
|
|
};
|
|
|
|
|
2017-10-13 22:30:57 +00:00
|
|
|
const binOptionsReduceFunction = function (binSize, prev, next) {
|
|
|
|
|
|
|
|
if (prev.length === 0) {
|
|
|
|
prev.push([next]);
|
|
|
|
return prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
const mostRecentBin = prev[prev.length - 1];
|
|
|
|
if (mostRecentBin.length < binSize) {
|
|
|
|
mostRecentBin.push(next);
|
|
|
|
return prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
prev.push([next]);
|
|
|
|
return prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
const pack = function (options, selected) {
|
|
|
|
|
|
|
|
const numBuckets = Math.ceil(options.length / bucketSize);
|
|
|
|
const binToBucketSizeFunc = binOptionsReduceFunction.bind(undefined, bucketSize);
|
|
|
|
options.sort();
|
|
|
|
|
|
|
|
const binnedOptions = options.reduce(binToBucketSizeFunc, []);
|
|
|
|
const bitFields = new Uint8Array(numBuckets);
|
|
|
|
|
2017-10-14 20:24:18 +00:00
|
|
|
let i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < numBuckets; i += 1) {
|
2017-10-13 22:30:57 +00:00
|
|
|
let bitfield = 0;
|
|
|
|
let currentBucket = binnedOptions[i];
|
|
|
|
|
2017-10-14 20:24:18 +00:00
|
|
|
for (j = 0; j < currentBucket.length; j += 1) {
|
2017-10-13 22:30:57 +00:00
|
|
|
|
|
|
|
let currentOption = currentBucket[j];
|
|
|
|
if (selected.indexOf(currentOption) !== -1) {
|
|
|
|
bitfield |= 1 << j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bitFields[i] = bitfield;
|
|
|
|
}
|
|
|
|
|
2017-10-14 04:23:49 +00:00
|
|
|
const encodedString = bufferToBase64(bitFields);
|
|
|
|
return encodedString;
|
2017-10-13 22:30:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const unpack = function (options, data) {
|
|
|
|
|
|
|
|
const binToBucketSizeFunc = binOptionsReduceFunction.bind(undefined, bucketSize);
|
|
|
|
options.sort();
|
|
|
|
|
|
|
|
const binnedOptions = options.reduce(binToBucketSizeFunc, []);
|
2017-10-14 04:23:49 +00:00
|
|
|
const bitFields = base64ToBuffer(data);
|
2017-10-13 22:30:57 +00:00
|
|
|
|
|
|
|
const result = [];
|
|
|
|
|
2017-10-14 20:24:18 +00:00
|
|
|
let i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < bitFields.length; i += 1) {
|
2017-10-13 22:30:57 +00:00
|
|
|
let currentBitField = bitFields[i];
|
|
|
|
let currentOptionsBin = binnedOptions[i];
|
|
|
|
|
2017-10-14 20:24:18 +00:00
|
|
|
for (j = 0; j < bucketSize; j += 1) {
|
2017-10-13 22:30:57 +00:00
|
|
|
if (currentBitField & (1 << j)) {
|
|
|
|
let currentOption = currentOptionsBin[j];
|
|
|
|
result.push(currentOption);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
window.WEB_API_MANAGER.packingLib = {
|
2017-10-14 20:24:18 +00:00
|
|
|
pack,
|
|
|
|
unpack
|
2017-10-13 22:30:57 +00:00
|
|
|
};
|
|
|
|
}());
|