UNPKG

id-shorter

Version:

A little module that replaces a long ObjectId value with short one keeping uniqueness. A charset for conversion is fully configurable and does not depend on requirement of 64 symbols. So it is possible to use only letters, letters+digits, digits etc.

198 lines (159 loc) 4.01 kB
var Utils = require('./utils'); var DEFAULT_BASESET = '0123456789'; var DEFAULT_FULL_BASESET = '0123456789abcdef'; var DEFAULT_ENCODINGSET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' module.exports = function(params) { params = params || {}; // Defaut encoding var baseCharSet = new Utils.BaseCharSet(DEFAULT_BASESET); var encodingCharSet = new Utils.EncodingCharSet(DEFAULT_ENCODINGSET); var isFullId = false; var isInverse = true; // Setters var setBase = function(set) { baseCharSet = new Utils.BaseCharSet(set); } var setEncoding = function(set) { encodingCharSet = new Utils.EncodingCharSet(set); } var setFullId = function(value) { isFullId = !!value; if (isFullId) { if (baseCharSet.set == DEFAULT_BASESET) { baseCharSet = new Utils.BaseCharSet(DEFAULT_FULL_BASESET); } } else { baseCharSet = new Utils.BaseCharSet(DEFAULT_BASESET); } } var inverse = function(value) { isInverse = !!value; } // Set isFullId first becasuse it changes baseSet to default if ('isFullId' in params) { setFullId(params.isFullId); } if (params.base) { setBase(params.base); } if (params.encoding) { setEncoding(params.encoding); } if ('isInverse' in params) { inverse(params.isInverse); } var BitStream = function(input, base) { var bitBuffer = []; var position = 0; for (var i = 0; i < input.length; i++) { var char = input.charAt(i); var value = base.map[char]; if (char == base.escapeChar && (i + 1 < input.length)) { // Escaped char var nextChar = input.charAt(++i); value = base.set.length + base.map[nextChar]; } if (isNaN(value)) { console.error('Invalid char "' + char + '" in input'); // Clear buffer bitBuffer = []; break; } var bitValue = Utils.padLeft(value.toString(2), base.bits, '0'); // console.log(value + ' | ' + baseBits + ' | ' + bitValue); bitBuffer = bitBuffer.concat(bitValue.split('')); } // console.log('BitBuffer:', bitBuffer); var stream = { rewind: function() { position = 0; }, isEOF: function() { return position == bitBuffer.length; }, getBits: function(bits) { if (stream.isEOF()) { return; } var requestedBits = bitBuffer.slice(position, position + bits).join(''); position += requestedBits.length; var value = parseInt(requestedBits, 2); return value; }, } return stream; } return { //setFullId: setFullId, //setBase: setBase, //setEncoding: setEncoding, //inverse: inverse, encode: function(input) { if (!isFullId && baseCharSet.set == DEFAULT_BASESET) { input = Utils.getObjectIdTime(input); } var bitStream = BitStream(String(input), baseCharSet); var result = ''; while (!bitStream.isEOF()) { var value = bitStream.getBits(encodingCharSet.bits); var nextChar = encodingCharSet.encode(value); if (isInverse) { result = nextChar + result; } else { result += nextChar; } } return result; }, decode: function(input) { if (isInverse) { if (encodingCharSet.escapeChar !== undefined) { var reverseStr = ''; var pos = 0; while (pos < input.length) { var char = input.charAt(pos++); if (char == encodingCharSet.escapeChar) { char += input.charAt(pos++); } reverseStr = char + reverseStr; } input = reverseStr; } else { input = input.split().reverse().join(); } } var bitStream = BitStream(String(input), encodingCharSet); var result = ''; while (!bitStream.isEOF()) { var value = bitStream.getBits(baseCharSet.bits); var char = baseCharSet.set.charAt(value); result += char; } return result; } }; }