aboutsummaryrefslogtreecommitdiffhomepage
path: root/node_modules/socket.io-parser/binary.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/socket.io-parser/binary.js')
-rw-r--r--node_modules/socket.io-parser/binary.js141
1 files changed, 141 insertions, 0 deletions
diff --git a/node_modules/socket.io-parser/binary.js b/node_modules/socket.io-parser/binary.js
new file mode 100644
index 0000000..1a530c7
--- /dev/null
+++ b/node_modules/socket.io-parser/binary.js
@@ -0,0 +1,141 @@
+/*global Blob,File*/
+
+/**
+ * Module requirements
+ */
+
+var isArray = require('isarray');
+var isBuf = require('./is-buffer');
+var toString = Object.prototype.toString;
+var withNativeBlob = typeof global.Blob === 'function' || toString.call(global.Blob) === '[object BlobConstructor]';
+var withNativeFile = typeof global.File === 'function' || toString.call(global.File) === '[object FileConstructor]';
+
+/**
+ * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
+ * Anything with blobs or files should be fed through removeBlobs before coming
+ * here.
+ *
+ * @param {Object} packet - socket.io event packet
+ * @return {Object} with deconstructed packet and list of buffers
+ * @api public
+ */
+
+exports.deconstructPacket = function(packet) {
+ var buffers = [];
+ var packetData = packet.data;
+ var pack = packet;
+ pack.data = _deconstructPacket(packetData, buffers);
+ pack.attachments = buffers.length; // number of binary 'attachments'
+ return {packet: pack, buffers: buffers};
+};
+
+function _deconstructPacket(data, buffers) {
+ if (!data) return data;
+
+ if (isBuf(data)) {
+ var placeholder = { _placeholder: true, num: buffers.length };
+ buffers.push(data);
+ return placeholder;
+ } else if (isArray(data)) {
+ var newData = new Array(data.length);
+ for (var i = 0; i < data.length; i++) {
+ newData[i] = _deconstructPacket(data[i], buffers);
+ }
+ return newData;
+ } else if (typeof data === 'object' && !(data instanceof Date)) {
+ var newData = {};
+ for (var key in data) {
+ newData[key] = _deconstructPacket(data[key], buffers);
+ }
+ return newData;
+ }
+ return data;
+}
+
+/**
+ * Reconstructs a binary packet from its placeholder packet and buffers
+ *
+ * @param {Object} packet - event packet with placeholders
+ * @param {Array} buffers - binary buffers to put in placeholder positions
+ * @return {Object} reconstructed packet
+ * @api public
+ */
+
+exports.reconstructPacket = function(packet, buffers) {
+ packet.data = _reconstructPacket(packet.data, buffers);
+ packet.attachments = undefined; // no longer useful
+ return packet;
+};
+
+function _reconstructPacket(data, buffers) {
+ if (!data) return data;
+
+ if (data && data._placeholder) {
+ return buffers[data.num]; // appropriate buffer (should be natural order anyway)
+ } else if (isArray(data)) {
+ for (var i = 0; i < data.length; i++) {
+ data[i] = _reconstructPacket(data[i], buffers);
+ }
+ } else if (typeof data === 'object') {
+ for (var key in data) {
+ data[key] = _reconstructPacket(data[key], buffers);
+ }
+ }
+
+ return data;
+}
+
+/**
+ * Asynchronously removes Blobs or Files from data via
+ * FileReader's readAsArrayBuffer method. Used before encoding
+ * data as msgpack. Calls callback with the blobless data.
+ *
+ * @param {Object} data
+ * @param {Function} callback
+ * @api private
+ */
+
+exports.removeBlobs = function(data, callback) {
+ function _removeBlobs(obj, curKey, containingObject) {
+ if (!obj) return obj;
+
+ // convert any blob
+ if ((withNativeBlob && obj instanceof Blob) ||
+ (withNativeFile && obj instanceof File)) {
+ pendingBlobs++;
+
+ // async filereader
+ var fileReader = new FileReader();
+ fileReader.onload = function() { // this.result == arraybuffer
+ if (containingObject) {
+ containingObject[curKey] = this.result;
+ }
+ else {
+ bloblessData = this.result;
+ }
+
+ // if nothing pending its callback time
+ if(! --pendingBlobs) {
+ callback(bloblessData);
+ }
+ };
+
+ fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
+ } else if (isArray(obj)) { // handle array
+ for (var i = 0; i < obj.length; i++) {
+ _removeBlobs(obj[i], i, obj);
+ }
+ } else if (typeof obj === 'object' && !isBuf(obj)) { // and object
+ for (var key in obj) {
+ _removeBlobs(obj[key], key, obj);
+ }
+ }
+ }
+
+ var pendingBlobs = 0;
+ var bloblessData = data;
+ _removeBlobs(bloblessData);
+ if (!pendingBlobs) {
+ callback(bloblessData);
+ }
+};