UNPKG

diffusion

Version:

Diffusion JavaScript client

328 lines (281 loc) 7.66 kB
/*eslint valid-jsdoc: "off"*/ var Long = require('long'); // Bitmasks for int64 read/write var x80 = Long.fromNumber(0x80), x7F = Long.fromNumber(0x7F), // Long.not returns a different value than ~ x7FInv = x7F.not(); //Long.fromNumber(~0x7F); /** * Helper function * @private */ var readOneByte = function(input) { var i = input.read(); if (i === -1) { throw new Error("End of stream"); } return i; }; /** * Javascript implementation of Encoded Data Codec, used for Command Service serialisers * * @namespace * @alias Encoded Data Codec */ var codec = {}; /** * Read an encoded Int64. * <P> * This will return the value as a Long instance. * * @param {BufferInputStream} - The input stream from which to read * @returns {Long} The decoded Int64, represented as Long * @throws A malformed error if an int64 cannot be read. */ codec.readInt64 = function(input) { var result = Long.fromNumber(0), shift = 0; while (shift < 64) { var i = readOneByte(input), l = Long.fromNumber(i); result = result.or(l.and(x7F).shiftLeft(shift)); if (l.and(x80).equals(0)) { return result; } shift += 7; } throw "Malformed int64"; }; /** * Write an encoded Int64. * <P> * Writes a number as an Int64 to the given Output stream. * * @param {BufferOutputStream} - The output stream to write to * @param {Number} - The number to write */ codec.writeInt64 = function(bos, value) { var int64 = value instanceof Long ? value : Long.fromNumber(value, false); for (;;) { if (int64.and(x7FInv).equals(0)) { bos.write(int64.toInt()); return; } else { bos.write(int64.and(x7F).or(x80).toInt()); int64 = int64.shiftRightUnsigned(7); } } }; /** * Read an encoded Int32. * * @param {BufferInputStream} - The input stream to read from. * @returns {Number} The Int32 that was read * @throws A malformed error if an int32 cannot be read */ codec.readInt32 = function(bis) { var shift = 0, result = 0; while (shift < 32) { var i = readOneByte(bis); result |= (i & 0x7F) << shift; if ((i & 0x80) === 0) { return result; } shift += 7; } throw "Malformed int32"; }; /** * Write an encoded Int32. * * @param {BufferOutputStream} - The output stream to write to. * @param {Number} - The number to write as an int32. */ codec.writeInt32 = function(bos, value) { for (;;) { if ((value & ~0x7F) === 0) { bos.write(value); return; } else { bos.write((value & 0x7F) | 0x80); value = value >>> 7; } } }; /** * Write a single signed byte. * * @param {BufferOutputStream} - The output stream to write to. * @param {Number} - The byte value to write. Must be between -128 & 127. */ codec.writeByte = function(bos, value) { bos.writeInt8(value); if ((value & ~0x7F) !== 0) { bos.write(1); } }; /** * Read a single signed byte. * * @param {BufferInputStream} - The input stream to read from. * @returns {Number} - The byte that was read. * @throws A malformed error if the byte couldn't be read. */ codec.readByte = function(bis) { var b1 = bis.readInt8(); if ((b1 & ~0x7F) === 0) { return b1; } var b2 = readOneByte(bis); if (b2 !== 1) { throw "Malformed byte"; } return (b1 | 0x80); }; /** * Read bytes as a Buffer. * * @param {BufferInputStream} - The input stream to read from. * @returns {Buffer} - The bytes that were read. */ codec.readBytes = function(bis) { var length = codec.readInt32(bis); return bis.readMany(length); }; /** * Write multiple bytes. * * @param {BufferOutputStream} - The output stream to write to. * @param {Buffer} - The bytes to be written. */ codec.writeBytes = function(bos, value) { codec.writeInt32(bos, value.length); bos.writeMany(value); }; /** * Read a UTF-8 encoded String. * * @param {BufferInputStream} - The input stream to read from. * @returns {String} The string that was read. */ codec.readString = function(bis) { var buffer = codec.readBytes(bis); return buffer ? buffer.toString('utf8') : ""; }; /** * Write a string using UTF-8 encoding. * * @param {BufferOutputStream} - The output stream to write to. * @param {String} - The string to write. */ codec.writeString = function(bos, value) { codec.writeBytes(bos, new Buffer(value, 'utf8')); }; /** * Write a collection of objects, using a specific writer function * * @param {BufferOutputStream} - The output stream to write to * @param {Array} - Array of values * @param {Function} - Writer function */ codec.writeCollection = function(bos, arr, write) { codec.writeInt32(bos, arr.length); for (var i = 0; i < arr.length; ++i) { write(bos, arr[i]); } }; /** * Read a collection of objects, using a specific reader function * * @param {BufferInputStream} - The inpit stream to read from * @param {Function} - Reader function * @returns {Array} An array of read values */ codec.readCollection = function(bis, read) { var length = codec.readInt32(bis); var arr = []; for (var i = 0; i < length; ++i) { arr.push(read(bis)); } return arr; }; /** * Read a dictionary of strings and values of a given type. * * @param {BufferInputStream} - The input stream to read from * @param {Function} - Value reader function * @returns {Object.<String, Object>} A dictionary of values */ codec.readDictionary = function(bis, read) { return codec.readMap(bis, codec.readString, read); }; /** * Write a dictionary of strings and values. * * @param {BufferOutputStream} - The output stream to write to * @param {Object.<String, Object>} - The dictionary of values * @param {Function} - Value writer function */ codec.writeDictionary = function(bos, dict, write) { codec.writeMap(bos, dict, codec.writeString, write); }; /** * Write a map of keys/values. * * @param {BufferOutputStream} bos - The output stream to write to * @param {Object} dict - The map of values * @param {Function} key - The Key writer function * @param {Function} value - The Value writer function */ codec.writeMap = function(bos, dict, key, value) { codec.writeInt32(bos, Object.keys(dict).length); for (var k in dict) { key(bos, k); value(bos, dict[k]); } }; /** * Read a map of keys/values. * * @param {BufferOutputStream} bos - The output stream to write to * @param {Object} dict - The map of values * @param {Function} key - The Key reader function * @param {Function} value - The Value reader function * @returns {Object} The read map */ codec.readMap = function(bis, key, value) { var length = codec.readInt32(bis); var dict = {}; for (var i = 0; i < length; ++i) { var k = key(bis); dict[k] = value(bis); } return dict; }; /** * Read a boolean value. * * @param {BufferInputStream} - The input stream to read from. * @returns {boolean} - The boolean that was read. */ codec.readBoolean = function(bis) { var b = bis.readInt8(); if (b === 0) { return false; } return true; }; /** * Write a boolean value. * * @param {BufferOutputStream} - The output stream to write to. * @param {value} - The boolean value to write. */ codec.writeBoolean = function(bos, value) { if (value) { bos.writeInt8(1); } else { bos.writeInt8(0); } }; module.exports = codec;