/** * Module dependencies. */ var json; try { json = require('json'); } catch(e){ json = JSON; } /** * Protocol version. * * @api public */ exports.protocol = 1; /** * Packet types. * * @api public */ exports.types = [ 'CONNECT', 'DISCONNECT', 'EVENT', 'ACK', 'ERROR' ]; /** * Packet type `connect`. * * @api public */ exports.CONNECT = 0; /** * Packet type `disconnect`. * * @api public */ exports.DISCONNECT = 1; /** * Packet type `event`. * * @api public */ exports.EVENT = 2; /** * Packet type `ack`. * * @api public */ exports.ACK = 3; /** * Packet type `error`. * * @api public */ exports.ERROR = 4; /** * Encode. * * @param {Object} packet * @return {String} encoded * @api public */ exports.encode = function(obj){ var str = ''; var nsp = false; // first is type str += obj.type; // if we have a namespace other than `/` // we append it followed by a comma `,` if (obj.nsp && '/' != obj.nsp) { nsp = true; str += obj.nsp; } // immediately followed by the id if (obj.id) { if (nsp) { str += ','; nsp = false; } str += obj.id; } // json data if (obj.data) { if (nsp) str += ','; str += json.stringify(obj.data); } return str; }; /** * Decode. * * @param {String} str * @return {Object} packet * @api public */ exports.decode = function(str){ var p = {}; var i = 0; // look up type p.type = Number(str.charAt(0)); if (null == exports.types[p.type]) return error(); // look up namespace (if any) if ('/' == str.charAt(i + 1)) { p.nsp = ''; while (++i) { var c = str.charAt(i); if (',' == c) break; p.nsp += c; if (i + 1 == str.length) break; } } else { p.nsp = '/'; } // look up id var next = str.charAt(i + 1); if ('' != next && Number(next) == next) { p.id = ''; while (++i) { var c = str.charAt(i); if (null == c || Number(c) != c) { --i; break; } p.id += str.charAt(i); if (i + 1 == str.length) break; } } // look up json data if (str.charAt(++i)) { try { p.data = json.parse(str.substr(i)); } catch(e){ return error(); } } return p; }; function error(data){ return { type: exports.ERROR, data: 'parser error' }; }