var Transform = require("stream").Transform; /** * A Transform Stream implementation that output full VNB protocol messages * * @constructor * @this {VNBMessageParser} */ function VNBMessageTransform(opts) { "use strict"; Transform.call(this,opts); var buffer; /** * Transform stream Write implementation * @param {string} data Upstream data already converted as string * @param {string} encoding String encoding (should be utf8, but should be checked upward) * @param {function} callback Downstream Stream receiving only full VNB messages **/ this._transform = function(data, encoding, callback) { var endpos = data.indexOf("\n"); if (endpos > -1) { if (buffer !== undefined) { this.push(buffer); buffer = undefined; } if (endpos > 0) { this.push(data.substr(0, endpos)); } callback(); if (endpos < data.length - 1) { buffer = data.substr(endpos + 1); } } else { buffer = buffer.concat(data); } }; /** * Flush still data. Remaining data is lost since it can only be an incomplete message * @param {function} callback Callback to call when data has been flushed **/ this._flush = function (callback) { buffer = undefined; callback(); }; } /** * VNB Client implementation (communication from vim to the netbeans server) * @constructor * @this {VNBMessageClient} * @param {stream.Readable} data Incomming stream * @param {function} onEvent Callback function called when an Event message is received * @param {function} onReply Callback function called when a Reply to a previous Function called is received */ function VNBMessageClient(data, onEvent, onReply) { "use strict"; data.setEncoding("utf8"); var messageTransform = new VNBMessageTransform(); messageTransform.on("data",function (message) { var iName = 0; //Index of the name separator in case of an Event var iSeqno = 0; //Index of the seqno separator in case of an Event //Header of the message for (var i = 0 ; i < message.length && message[i] !== " "; ++i) { if (message[i] === ":") { iName = i; } else if (message[i] === "=") { iSeqno = i; } } var isEvent = false; var args = []; if (iName > 0 && iSeqno > 0) { isEvent = true; args.push(Number.parseInt(message.substr(0, iName), 10)); args.push(message.substring(iName + 1, iSeqno)); args.push(Number.parseInt(message.substring(iSeqno + 1, i), 10)); } else if (iName === 0 && iSeqno === 0) { args.push(Number.parseInt(message.substr(0, i), 10)); } else { //Unknown message type } //Arguments of the message for (++i ; i < message.length ; ++i) { } if (isEvent) { onEvent(...args); } else { onReply(...args); } }); messageTransform.on("error", function (error) { }); messageTransform.on("end",function () { }); messageTransform.on("close", function () { }); data.pipe(messageTransform); }