You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by ra...@apache.org on 2015/02/10 11:32:00 UTC
[2/3] thrift git commit: THRIFT-2964: nodejs file breakout Client:
NodeJS Patch: Andrew de Andrade
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/json_protocol.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/json_protocol.js b/lib/nodejs/lib/thrift/json_protocol.js
new file mode 100644
index 0000000..f4678f5
--- /dev/null
+++ b/lib/nodejs/lib/thrift/json_protocol.js
@@ -0,0 +1,706 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+var log = require('./log');
+var Int64 = require('node-int64');
+var InputBufferUnderrunError = require('./transport').InputBufferUnderrunError;
+var Thrift = require('./thrift');
+var Type = Thrift.Type;
+var util = require("util");
+
+var InputBufferUnderrunError = require('./input_buffer_underrun_error');
+
+module.exports = TJSONProtocol;
+
+/**
+ * Initializes a Thrift JSON protocol instance.
+ * @constructor
+ * @param {Thrift.Transport} trans - The transport to serialize to/from.
+ * @classdesc Apache Thrift Protocols perform serialization which enables cross
+ * language RPC. The Protocol type is the JavaScript browser implementation
+ * of the Apache Thrift TJSONProtocol.
+ * @example
+ * var protocol = new Thrift.Protocol(transport);
+ */
+function TJSONProtocol(trans) {
+ this.trans = trans;
+};
+
+/**
+ * Thrift IDL type Id to string mapping.
+ * @readonly
+ * @see {@link Thrift.Type}
+ */
+TJSONProtocol.Type = {};
+TJSONProtocol.Type[Type.BOOL] = '"tf"';
+TJSONProtocol.Type[Type.BYTE] = '"i8"';
+TJSONProtocol.Type[Type.I16] = '"i16"';
+TJSONProtocol.Type[Type.I32] = '"i32"';
+TJSONProtocol.Type[Type.I64] = '"i64"';
+TJSONProtocol.Type[Type.DOUBLE] = '"dbl"';
+TJSONProtocol.Type[Type.STRUCT] = '"rec"';
+TJSONProtocol.Type[Type.STRING] = '"str"';
+TJSONProtocol.Type[Type.MAP] = '"map"';
+TJSONProtocol.Type[Type.LIST] = '"lst"';
+TJSONProtocol.Type[Type.SET] = '"set"';
+
+/**
+ * Thrift IDL type string to Id mapping.
+ * @readonly
+ * @see {@link Thrift.Type}
+ */
+TJSONProtocol.RType = {};
+TJSONProtocol.RType.tf = Type.BOOL;
+TJSONProtocol.RType.i8 = Type.BYTE;
+TJSONProtocol.RType.i16 = Type.I16;
+TJSONProtocol.RType.i32 = Type.I32;
+TJSONProtocol.RType.i64 = Type.I64;
+TJSONProtocol.RType.dbl = Type.DOUBLE;
+TJSONProtocol.RType.rec = Type.STRUCT;
+TJSONProtocol.RType.str = Type.STRING;
+TJSONProtocol.RType.map = Type.MAP;
+TJSONProtocol.RType.lst = Type.LIST;
+TJSONProtocol.RType.set = Type.SET;
+
+/**
+ * The TJSONProtocol version number.
+ * @readonly
+ * @const {number} Version
+ * @memberof Thrift.Protocol
+ */
+TJSONProtocol.Version = 1;
+
+TJSONProtocol.prototype.flush = function() {
+ return this.trans.flush();
+};
+
+/**
+ * Serializes the beginning of a Thrift RPC message.
+ * @param {string} name - The service method to call.
+ * @param {Thrift.MessageType} messageType - The type of method call.
+ * @param {number} seqid - The sequence number of this call (always 0 in Apache Thrift).
+ */
+TJSONProtocol.prototype.writeMessageBegin = function(name, messageType, seqid) {
+ this.tstack = [];
+ this.tpos = [];
+
+ this.tstack.push([TJSONProtocol.Version, '"' + name + '"', messageType, seqid]);
+};
+
+/**
+ * Serializes the end of a Thrift RPC message.
+ */
+TJSONProtocol.prototype.writeMessageEnd = function() {
+ var obj = this.tstack.pop();
+
+ this.wobj = this.tstack.pop();
+ this.wobj.push(obj);
+
+ this.wbuf = '[' + this.wobj.join(',') + ']';
+
+ this.trans.write(this.wbuf);
+};
+
+/**
+ * Serializes the beginning of a struct.
+ * @param {string} name - The name of the struct.
+ */
+TJSONProtocol.prototype.writeStructBegin = function(name) {
+ this.tpos.push(this.tstack.length);
+ this.tstack.push({});
+};
+
+/**
+ * Serializes the end of a struct.
+ */
+TJSONProtocol.prototype.writeStructEnd = function() {
+ var p = this.tpos.pop();
+ var struct = this.tstack[p];
+ var str = '{';
+ var first = true;
+ for (var key in struct) {
+ if (first) {
+ first = false;
+ } else {
+ str += ',';
+ }
+
+ str += key + ':' + struct[key];
+ }
+
+ str += '}';
+ this.tstack[p] = str;
+};
+
+/**
+ * Serializes the beginning of a struct field.
+ * @param {string} name - The name of the field.
+ * @param {Thrift.Protocol.Type} fieldType - The data type of the field.
+ * @param {number} fieldId - The field's unique identifier.
+ */
+TJSONProtocol.prototype.writeFieldBegin = function(name, fieldType, fieldId) {
+ this.tpos.push(this.tstack.length);
+ this.tstack.push({ 'fieldId': '"' +
+ fieldId + '"', 'fieldType': TJSONProtocol.Type[fieldType]
+ });
+};
+
+/**
+ * Serializes the end of a field.
+ */
+TJSONProtocol.prototype.writeFieldEnd = function() {
+ var value = this.tstack.pop();
+ var fieldInfo = this.tstack.pop();
+
+ if (':' + value === ":[object Object]") {
+ this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
+ fieldInfo.fieldType + ':' + JSON.stringify(value) + '}';
+ } else {
+ this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
+ fieldInfo.fieldType + ':' + value + '}';
+ }
+ this.tpos.pop();
+};
+
+/**
+ * Serializes the end of the set of fields for a struct.
+ */
+TJSONProtocol.prototype.writeFieldStop = function() {
+};
+
+/**
+ * Serializes the beginning of a map collection.
+ * @param {Thrift.Type} keyType - The data type of the key.
+ * @param {Thrift.Type} valType - The data type of the value.
+ * @param {number} [size] - The number of elements in the map (ignored).
+ */
+TJSONProtocol.prototype.writeMapBegin = function(keyType, valType, size) {
+ //size is invalid, we'll set it on end.
+ this.tpos.push(this.tstack.length);
+ this.tstack.push([TJSONProtocol.Type[keyType], TJSONProtocol.Type[valType], 0]);
+};
+
+/**
+ * Serializes the end of a map.
+ */
+TJSONProtocol.prototype.writeMapEnd = function() {
+ var p = this.tpos.pop();
+
+ if (p == this.tstack.length) {
+ return;
+ }
+
+ if ((this.tstack.length - p - 1) % 2 !== 0) {
+ this.tstack.push('');
+ }
+
+ var size = (this.tstack.length - p - 1) / 2;
+
+ this.tstack[p][this.tstack[p].length - 1] = size;
+
+ var map = '}';
+ var first = true;
+ while (this.tstack.length > p + 1) {
+ var v = this.tstack.pop();
+ var k = this.tstack.pop();
+ if (first) {
+ first = false;
+ } else {
+ map = ',' + map;
+ }
+
+ if (! isNaN(k)) { k = '"' + k + '"'; } //json "keys" need to be strings
+ map = k + ':' + v + map;
+ }
+ map = '{' + map;
+
+ this.tstack[p].push(map);
+ this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
+};
+
+/**
+ * Serializes the beginning of a list collection.
+ * @param {Thrift.Type} elemType - The data type of the elements.
+ * @param {number} size - The number of elements in the list.
+ */
+TJSONProtocol.prototype.writeListBegin = function(elemType, size) {
+ this.tpos.push(this.tstack.length);
+ this.tstack.push([TJSONProtocol.Type[elemType], size]);
+};
+
+/**
+ * Serializes the end of a list.
+ */
+TJSONProtocol.prototype.writeListEnd = function() {
+ var p = this.tpos.pop();
+
+ while (this.tstack.length > p + 1) {
+ var tmpVal = this.tstack[p + 1];
+ this.tstack.splice(p + 1, 1);
+ this.tstack[p].push(tmpVal);
+ }
+
+ this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
+};
+
+/**
+ * Serializes the beginning of a set collection.
+ * @param {Thrift.Type} elemType - The data type of the elements.
+ * @param {number} size - The number of elements in the list.
+ */
+TJSONProtocol.prototype.writeSetBegin = function(elemType, size) {
+ this.tpos.push(this.tstack.length);
+ this.tstack.push([TJSONProtocol.Type[elemType], size]);
+};
+
+/**
+ * Serializes the end of a set.
+ */
+TJSONProtocol.prototype.writeSetEnd = function() {
+ var p = this.tpos.pop();
+
+ while (this.tstack.length > p + 1) {
+ var tmpVal = this.tstack[p + 1];
+ this.tstack.splice(p + 1, 1);
+ this.tstack[p].push(tmpVal);
+ }
+
+ this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
+};
+
+/** Serializes a boolean */
+TJSONProtocol.prototype.writeBool = function(bool) {
+ this.tstack.push(bool ? 1 : 0);
+};
+
+/** Serializes a number */
+TJSONProtocol.prototype.writeByte = function(byte) {
+ this.tstack.push(byte);
+};
+
+/** Serializes a number */
+TJSONProtocol.prototype.writeI16 = function(i16) {
+ this.tstack.push(i16);
+};
+
+/** Serializes a number */
+TJSONProtocol.prototype.writeI32 = function(i32) {
+ this.tstack.push(i32);
+};
+
+/** Serializes a number */
+TJSONProtocol.prototype.writeI64 = function(i64) {
+ this.tstack.push(i64);
+};
+
+/** Serializes a number */
+TJSONProtocol.prototype.writeDouble = function(dub) {
+ this.tstack.push(dub);
+};
+
+/** Serializes a string */
+TJSONProtocol.prototype.writeString = function(str) {
+ // We do not encode uri components for wire transfer:
+ if (str === null) {
+ this.tstack.push(null);
+ } else {
+ // concat may be slower than building a byte buffer
+ var escapedString = '';
+ for (var i = 0; i < str.length; i++) {
+ var ch = str.charAt(i); // a single double quote: "
+ if (ch === '\"') {
+ escapedString += '\\\"'; // write out as: \"
+ } else if (ch === '\\') { // a single backslash: \
+ escapedString += '\\\\'; // write out as: \\
+ /* Currently escaped forward slashes break TJSONProtocol.
+ * As it stands, we can simply pass forward slashes into
+ * our strings across the wire without being escaped.
+ * I think this is the protocol's bug, not thrift.js
+ * } else if(ch === '/') { // a single forward slash: /
+ * escapedString += '\\/'; // write out as \/
+ * }
+ */
+ } else if (ch === '\b') { // a single backspace: invisible
+ escapedString += '\\b'; // write out as: \b"
+ } else if (ch === '\f') { // a single formfeed: invisible
+ escapedString += '\\f'; // write out as: \f"
+ } else if (ch === '\n') { // a single newline: invisible
+ escapedString += '\\n'; // write out as: \n"
+ } else if (ch === '\r') { // a single return: invisible
+ escapedString += '\\r'; // write out as: \r"
+ } else if (ch === '\t') { // a single tab: invisible
+ escapedString += '\\t'; // write out as: \t"
+ } else {
+ escapedString += ch; // Else it need not be escaped
+ }
+ }
+ this.tstack.push('"' + escapedString + '"');
+ }
+};
+
+/** Serializes a string */
+TJSONProtocol.prototype.writeBinary = function(arg) {
+ this.writeString(arg);
+};
+
+/**
+ * @class
+ * @name AnonReadMessageBeginReturn
+ * @property {string} fname - The name of the service method.
+ * @property {Thrift.MessageType} mtype - The type of message call.
+ * @property {number} rseqid - The sequence number of the message (0 in Thrift RPC).
+ */
+/**
+ * Deserializes the beginning of a message.
+ * @returns {AnonReadMessageBeginReturn}
+ */
+TJSONProtocol.prototype.readMessageBegin = function() {
+ this.rstack = [];
+ this.rpos = [];
+
+ //Borrow the inbound transport buffer and ensure data is present/consistent
+ var transBuf = this.trans.borrow();
+ if (transBuf.readIndex >= transBuf.writeIndex) {
+ throw new InputBufferUnderrunError();
+ }
+ var cursor = transBuf.readIndex;
+
+ if (transBuf.buf[cursor] !== 0x5B) { //[
+ throw new Error("Malformed JSON input, no opening bracket");
+ }
+
+ //Parse a single message (there may be several in the buffer)
+ // TODO: Handle characters using multiple code units
+ cursor++;
+ var openBracketCount = 1;
+ var inString = false;
+ for (; cursor < transBuf.writeIndex; cursor++) {
+ var chr = transBuf.buf[cursor];
+ //we use hexa charcode here because data[i] returns an int and not a char
+ if (inString) {
+ if (chr === 0x22) { //"
+ inString = false;
+ } else if (chr === 0x5C) { //\
+ //escaped character, skip
+ cursor += 1;
+ }
+ } else {
+ if (chr === 0x5B) { //[
+ openBracketCount += 1;
+ } else if (chr === 0x5D) { //]
+ openBracketCount -= 1;
+ if (openBracketCount === 0) {
+ //end of json message detected
+ break;
+ }
+ } else if (chr === 0x22) { //"
+ inString = true;
+ }
+ }
+ }
+
+ if (openBracketCount !== 0) {
+ throw new Error("Malformed JSON input, mismatched backets");
+ }
+
+ //Reconstitute the JSON object and conume the necessary bytes
+ this.robj = JSON.parse(transBuf.buf.slice(transBuf.readIndex, cursor+1));
+ this.trans.consume(cursor + 1 - transBuf.readIndex);
+
+ //Verify the protocol version
+ var version = this.robj.shift();
+ if (version != TJSONProtocol.Version) {
+ throw 'Wrong thrift protocol version: ' + version;
+ }
+
+ //Objectify the thrift message {name/type/sequence-number} for return
+ // and then save the JSON object in rstack
+ var r = {};
+ r.fname = this.robj.shift();
+ r.mtype = this.robj.shift();
+ r.rseqid = this.robj.shift();
+ this.rstack.push(this.robj.shift());
+ return r;
+};
+
+/** Deserializes the end of a message. */
+TJSONProtocol.prototype.readMessageEnd = function() {
+};
+
+/**
+ * Deserializes the beginning of a struct.
+ * @param {string} [name] - The name of the struct (ignored)
+ * @returns {object} - An object with an empty string fname property
+ */
+TJSONProtocol.prototype.readStructBegin = function() {
+ var r = {};
+ r.fname = '';
+
+ //incase this is an array of structs
+ if (this.rstack[this.rstack.length - 1] instanceof Array) {
+ this.rstack.push(this.rstack[this.rstack.length - 1].shift());
+ }
+
+ return r;
+};
+
+/** Deserializes the end of a struct. */
+TJSONProtocol.prototype.readStructEnd = function() {
+ this.rstack.pop();
+};
+
+/**
+ * @class
+ * @name AnonReadFieldBeginReturn
+ * @property {string} fname - The name of the field (always '').
+ * @property {Thrift.Type} ftype - The data type of the field.
+ * @property {number} fid - The unique identifier of the field.
+ */
+/**
+ * Deserializes the beginning of a field.
+ * @returns {AnonReadFieldBeginReturn}
+ */
+TJSONProtocol.prototype.readFieldBegin = function() {
+ var r = {};
+
+ var fid = -1;
+ var ftype = Type.STOP;
+
+ //get a fieldId
+ for (var f in (this.rstack[this.rstack.length - 1])) {
+ if (f === null) {
+ continue;
+ }
+
+ fid = parseInt(f, 10);
+ this.rpos.push(this.rstack.length);
+
+ var field = this.rstack[this.rstack.length - 1][fid];
+
+ //remove so we don't see it again
+ delete this.rstack[this.rstack.length - 1][fid];
+
+ this.rstack.push(field);
+
+ break;
+ }
+
+ if (fid != -1) {
+ //should only be 1 of these but this is the only
+ //way to match a key
+ for (var i in (this.rstack[this.rstack.length - 1])) {
+ if (TJSONProtocol.RType[i] === null) {
+ continue;
+ }
+
+ ftype = TJSONProtocol.RType[i];
+ this.rstack[this.rstack.length - 1] = this.rstack[this.rstack.length - 1][i];
+ }
+ }
+
+ r.fname = '';
+ r.ftype = ftype;
+ r.fid = fid;
+
+ return r;
+};
+
+/** Deserializes the end of a field. */
+TJSONProtocol.prototype.readFieldEnd = function() {
+ var pos = this.rpos.pop();
+
+ //get back to the right place in the stack
+ while (this.rstack.length > pos) {
+ this.rstack.pop();
+ }
+};
+
+/**
+ * @class
+ * @name AnonReadMapBeginReturn
+ * @property {Thrift.Type} ktype - The data type of the key.
+ * @property {Thrift.Type} vtype - The data type of the value.
+ * @property {number} size - The number of elements in the map.
+ */
+/**
+ * Deserializes the beginning of a map.
+ * @returns {AnonReadMapBeginReturn}
+ */
+TJSONProtocol.prototype.readMapBegin = function() {
+ var map = this.rstack.pop();
+
+ var r = {};
+ r.ktype = TJSONProtocol.RType[map.shift()];
+ r.vtype = TJSONProtocol.RType[map.shift()];
+ r.size = map.shift();
+
+
+ this.rpos.push(this.rstack.length);
+ this.rstack.push(map.shift());
+
+ return r;
+};
+
+/** Deserializes the end of a map. */
+TJSONProtocol.prototype.readMapEnd = function() {
+ this.readFieldEnd();
+};
+
+/**
+ * @class
+ * @name AnonReadColBeginReturn
+ * @property {Thrift.Type} etype - The data type of the element.
+ * @property {number} size - The number of elements in the collection.
+ */
+/**
+ * Deserializes the beginning of a list.
+ * @returns {AnonReadColBeginReturn}
+ */
+TJSONProtocol.prototype.readListBegin = function() {
+ var list = this.rstack[this.rstack.length - 1];
+
+ var r = {};
+ r.etype = TJSONProtocol.RType[list.shift()];
+ r.size = list.shift();
+
+ this.rpos.push(this.rstack.length);
+ this.rstack.push(list);
+
+ return r;
+};
+
+/** Deserializes the end of a list. */
+TJSONProtocol.prototype.readListEnd = function() {
+ this.readFieldEnd();
+};
+
+/**
+ * Deserializes the beginning of a set.
+ * @returns {AnonReadColBeginReturn}
+ */
+TJSONProtocol.prototype.readSetBegin = function() {
+ return this.readListBegin();
+};
+
+/** Deserializes the end of a set. */
+TJSONProtocol.prototype.readSetEnd = function() {
+ return this.readListEnd();
+};
+
+/** Returns an object with a value property set to
+ * False unless the next number in the protocol buffer
+ * is 1, in which case the value property is True */
+TJSONProtocol.prototype.readBool = function() {
+ var r = this.readI32();
+
+ if (r !== null && r.value == '1') {
+ r.value = true;
+ } else {
+ r.value = false;
+ }
+
+ return r;
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readByte = function() {
+ return this.readI32();
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readI16 = function() {
+ return this.readI32();
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readI32 = function(f) {
+ if (f === undefined) {
+ f = this.rstack[this.rstack.length - 1];
+ }
+
+ var r = {};
+
+ if (f instanceof Array) {
+ if (f.length === 0) {
+ r.value = undefined;
+ } else {
+ r.value = f.shift();
+ }
+ } else if (f instanceof Object) {
+ for (var i in f) {
+ if (i === null) {
+ continue;
+ }
+ this.rstack.push(f[i]);
+ delete f[i];
+
+ r.value = i;
+ break;
+ }
+ } else {
+ r.value = f;
+ this.rstack.pop();
+ }
+
+ return r.value;
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readI64 = function() {
+ return new Int64(this.readI32());
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readDouble = function() {
+ return this.readI32();
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readBinary = function() {
+ return this.readString();
+};
+
+/** Returns the an object with a value property set to the
+ next value found in the protocol buffer */
+TJSONProtocol.prototype.readString = function() {
+ var r = this.readI32();
+ return r;
+};
+
+/**
+ * Returns the underlying transport.
+ * @readonly
+ * @returns {Thrift.Transport} The underlying transport.
+ */
+TJSONProtocol.prototype.getTransport = function() {
+ return this.trans;
+};
+
+/**
+ * Method to arbitrarily skip over data
+ */
+TJSONProtocol.prototype.skip = function(type) {
+ throw 'skip not supported yet';
+};
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/log.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/log.js b/lib/nodejs/lib/thrift/log.js
new file mode 100644
index 0000000..0e13ea8
--- /dev/null
+++ b/lib/nodejs/lib/thrift/log.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+module.exports = {
+ 'info' : function logInfo() {},
+ 'warning' : function logWarning() {},
+ 'error' : function logError() {},
+ 'debug' : function logDebug() {},
+ 'trace' : function logTrace() {}
+};
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/multiplexed_processor.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/multiplexed_processor.js b/lib/nodejs/lib/thrift/multiplexed_processor.js
index fbceb79..67b62f7 100644
--- a/lib/nodejs/lib/thrift/multiplexed_processor.js
+++ b/lib/nodejs/lib/thrift/multiplexed_processor.js
@@ -18,41 +18,46 @@
*/
var Thrift = require('./thrift');
-var MultiplexedProcessor = exports.MultiplexedProcessor = function(stream, options) {
- this.services = {};
+exports.MultiplexedProcessor = MultiplexedProcessor;
+
+function MultiplexedProcessor(stream, options) {
+ this.services = {};
};
MultiplexedProcessor.prototype.registerProcessor = function(name, handler) {
- this.services[name] = handler;
+ this.services[name] = handler;
};
MultiplexedProcessor.prototype.process = function(inp, out) {
- var begin = inp.readMessageBegin();
- if (begin.mtype != Thrift.MessageType.CALL && begin.mtype != Thrift.MessageType.ONEWAY) {
- throw new Thrift.TException("TMultiplexedProcessor: Unexpected message type");
- }
-
- var p = begin.fname.split(":");
- var sname = p[0];
- var fname = p[1];
-
- if (! (sname in this.services)) {
- throw new Thrift.TException("TMultiplexedProcessor: Unknown service: " + sname);
- }
-
- //construct a proxy object which stubs the readMessageBegin
- //for the service
- var inpProxy = {};
- for (var attr in inp) {
- inpProxy[attr] = inp[attr];
- }
- inpProxy.readMessageBegin = function() {
- return {
- fname: fname,
- mtype: begin.mtype,
- rseqid: begin.rseqid
- };
+ var begin = inp.readMessageBegin();
+
+ if (begin.mtype != Thrift.MessageType.CALL && begin.mtype != Thrift.MessageType.ONEWAY) {
+ throw new Thrift.TException('TMultiplexedProcessor: Unexpected message type');
+ }
+
+ var p = begin.fname.split(':');
+ var sname = p[0];
+ var fname = p[1];
+
+ if (! (sname in this.services)) {
+ throw new Thrift.TException('TMultiplexedProcessor: Unknown service: ' + sname);
+ }
+
+ //construct a proxy object which stubs the readMessageBegin
+ //for the service
+ var inpProxy = {};
+
+ for (var attr in inp) {
+ inpProxy[attr] = inp[attr];
+ }
+
+ inpProxy.readMessageBegin = function() {
+ return {
+ fname: fname,
+ mtype: begin.mtype,
+ rseqid: begin.rseqid
};
+ };
- this.services[sname].process(inpProxy, out);
+ this.services[sname].process(inpProxy, out);
};
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/multiplexed_protocol.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/multiplexed_protocol.js b/lib/nodejs/lib/thrift/multiplexed_protocol.js
index 68440af..0745a1b 100644
--- a/lib/nodejs/lib/thrift/multiplexed_protocol.js
+++ b/lib/nodejs/lib/thrift/multiplexed_protocol.js
@@ -19,49 +19,56 @@
var util = require('util');
var Thrift = require('./thrift');
-var Wrapper = exports.Wrapper = function(service_name, protocol, connection) {
+exports.Wrapper = Wrapper;
+exports.Multiplexer = Multiplexer;
- var MultiplexProtocol = function(trans, strictRead, strictWrite) {
- protocol.call(this, trans, strictRead, strictWrite);
- };
- util.inherits(MultiplexProtocol, protocol);
+function Wrapper(serviceName, protocol, connection) {
- MultiplexProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
- if (type == Thrift.MessageType.CALL || type == Thrift.MessageType.ONEWAY) {
- connection.seqId2Service[seqid] = service_name;
- MultiplexProtocol.super_.prototype.writeMessageBegin.call(this,
- service_name + ":" + name,
- type,
- seqid);
- } else {
- MultiplexProtocol.super_.prototype.writeMessageBegin.call(this, name, type, seqid);
- }
- };
+ function MultiplexProtocol(trans, strictRead, strictWrite) {
+ protocol.call(this, trans, strictRead, strictWrite);
+ };
- return MultiplexProtocol;
+ util.inherits(MultiplexProtocol, protocol);
+
+ MultiplexProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
+ if (type == Thrift.MessageType.CALL || type == Thrift.MessageType.ONEWAY) {
+ connection.seqId2Service[seqid] = serviceName;
+ MultiplexProtocol.super_.prototype.writeMessageBegin.call(this,
+ serviceName + ":" + name,
+ type,
+ seqid);
+ } else {
+ MultiplexProtocol.super_.prototype.writeMessageBegin.call(this, name, type, seqid);
+ }
+ };
+
+ return MultiplexProtocol;
};
-var Multiplexer = exports.Multiplexer = function() {
- this.seqid = 0;
+function Multiplexer() {
+ this.seqid = 0;
};
-Multiplexer.prototype.createClient = function(service_name, cls, connection) {
- if (cls.Client) {
- cls = cls.Client;
- }
- var self = this;
- cls.prototype.new_seqid = function() {
- self.seqid += 1;
- return self.seqid;
- };
- var client = new cls(new connection.transport(undefined, function(buf) {
- connection.write(buf);
- }), new Wrapper(service_name, connection.protocol, connection));
-
- if (typeof connection.client !== 'object') {
- connection.client = {};
- }
- connection.client[service_name] = client;
+Multiplexer.prototype.createClient = function(serviceName, ServiceClient, connection) {
+ if (ServiceClient.Client) {
+ ServiceClient = ServiceClient.Client;
+ }
+ var self = this;
+ ServiceClient.prototype.new_seqid = function() {
+ self.seqid += 1;
+ return self.seqid;
+ };
+ var writeCb = function(buf, seqid) {
+ connection.write(buf,seqid);
+ };
+ var transport = new connection.transport(undefined, writeCb);
+ var protocolWrapper = new Wrapper(serviceName, connection.protocol, connection);
+ var client = new ServiceClient(transport, protocolWrapper);
+
+ if (typeof connection.client !== 'object') {
+ connection.client = {};
+ }
+ connection.client[serviceName] = client;
- return client;
+ return client;
};
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/protocol.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/protocol.js b/lib/nodejs/lib/thrift/protocol.js
index 6c8e8e6..a70ebe2 100644
--- a/lib/nodejs/lib/thrift/protocol.js
+++ b/lib/nodejs/lib/thrift/protocol.js
@@ -16,1728 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-var util = require('util'),
- Thrift = require('./thrift'),
- Type = Thrift.Type;
-
-var binary = require('./binary'),
- Int64 = require('node-int64');
-
-var InputBufferUnderrunError = require('./transport').InputBufferUnderrunError;
-
-//
-// BINARY PROTOCOL
-//
-///////////////////////////////////////////////////////////
-
-// JavaScript supports only numeric doubles, therefore even hex values are always signed.
-// The largest integer value which can be represented in JavaScript is +/-2^53.
-// Bitwise operations convert numbers to 32 bit integers but perform sign extension
-// upon assigning values back to variables.
-var VERSION_MASK = -65536, // 0xffff0000
- VERSION_1 = -2147418112, // 0x80010000
- TYPE_MASK = 0x000000ff;
-
-var POW_8 = Math.pow(2, 8);
-var POW_24 = Math.pow(2, 24);
-var POW_32 = Math.pow(2, 32);
-var POW_40 = Math.pow(2, 40);
-var POW_48 = Math.pow(2, 48);
-var POW_52 = Math.pow(2, 52);
-var POW_1022 = Math.pow(2, 1022);
-
-var TBinaryProtocol = exports.TBinaryProtocol = function(trans, strictRead, strictWrite) {
- this.trans = trans;
- this.strictRead = (strictRead !== undefined ? strictRead : false);
- this.strictWrite = (strictWrite !== undefined ? strictWrite : true);
-};
-
-TBinaryProtocol.prototype.flush = function() {
- return this.trans.flush();
-};
-
-TBinaryProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
- if (this.strictWrite) {
- this.writeI32(VERSION_1 | type);
- this.writeString(name);
- this.writeI32(seqid);
- } else {
- this.writeString(name);
- this.writeByte(type);
- this.writeI32(seqid);
- }
-};
-
-TBinaryProtocol.prototype.writeMessageEnd = function() {
-};
-
-TBinaryProtocol.prototype.writeStructBegin = function(name) {
-};
-
-TBinaryProtocol.prototype.writeStructEnd = function() {
-};
-
-TBinaryProtocol.prototype.writeFieldBegin = function(name, type, id) {
- this.writeByte(type);
- this.writeI16(id);
-};
-
-TBinaryProtocol.prototype.writeFieldEnd = function() {
-};
-
-TBinaryProtocol.prototype.writeFieldStop = function() {
- this.writeByte(Type.STOP);
-};
-
-TBinaryProtocol.prototype.writeMapBegin = function(ktype, vtype, size) {
- this.writeByte(ktype);
- this.writeByte(vtype);
- this.writeI32(size);
-};
-
-TBinaryProtocol.prototype.writeMapEnd = function() {
-};
-
-TBinaryProtocol.prototype.writeListBegin = function(etype, size) {
- this.writeByte(etype);
- this.writeI32(size);
-};
-
-TBinaryProtocol.prototype.writeListEnd = function() {
-};
-
-TBinaryProtocol.prototype.writeSetBegin = function(etype, size) {
- this.writeByte(etype);
- this.writeI32(size);
-};
-
-TBinaryProtocol.prototype.writeSetEnd = function() {
-};
-
-TBinaryProtocol.prototype.writeBool = function(bool) {
- if (bool) {
- this.writeByte(1);
- } else {
- this.writeByte(0);
- }
-};
-
-TBinaryProtocol.prototype.writeByte = function(b) {
- this.trans.write(new Buffer([b]));
-};
-
-TBinaryProtocol.prototype.writeI16 = function(i16) {
- this.trans.write(binary.writeI16(new Buffer(2), i16));
-};
-
-TBinaryProtocol.prototype.writeI32 = function(i32) {
- this.trans.write(binary.writeI32(new Buffer(4), i32));
-};
-
-TBinaryProtocol.prototype.writeI64 = function(i64) {
- if (i64.buffer) {
- this.trans.write(i64.buffer);
- } else {
- this.trans.write(new Int64(i64).buffer);
- }
-};
-
-TBinaryProtocol.prototype.writeDouble = function(dub) {
- this.trans.write(binary.writeDouble(new Buffer(8), dub));
-};
-
-TBinaryProtocol.prototype.writeString = function(arg) {
- if (typeof(arg) === 'string') {
- this.writeI32(Buffer.byteLength(arg, 'utf8'));
- this.trans.write(arg, 'utf8');
- } else if (arg instanceof Buffer) {
- this.writeI32(arg.length);
- this.trans.write(arg);
- } else {
- throw new Error('writeString called without a string/Buffer argument: ' + arg);
- }
-};
-
-TBinaryProtocol.prototype.writeBinary = function(arg) {
- if (typeof(arg) === 'string') {
- this.writeI32(Buffer.byteLength(arg, 'utf8'));
- this.trans.write(arg, 'utf8');
- } else if ((arg instanceof Buffer) ||
- (Object.prototype.toString.call(arg) == '[object Uint8Array]')) {
- // Buffers in Node.js under Browserify may extend UInt8Array instead of
- // defining a new object. We detect them here so we can write them
- // correctly
- this.writeI32(arg.length);
- this.trans.write(arg);
- } else {
- throw new Error('writeBinary called without a string/Buffer argument: ' + arg);
- }
-};
-
-TBinaryProtocol.prototype.readMessageBegin = function() {
- var sz = this.readI32();
- var type, name, seqid;
-
- if (sz < 0) {
- var version = sz & VERSION_MASK;
- if (version != VERSION_1) {
- console.log("BAD: " + version);
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad version in readMessageBegin: " + sz);
- }
- type = sz & TYPE_MASK;
- name = this.readString();
- seqid = this.readI32();
- } else {
- if (this.strictRead) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "No protocol version header");
- }
- name = this.trans.read(sz);
- type = this.readByte();
- seqid = this.readI32();
- }
- return {fname: name, mtype: type, rseqid: seqid};
-};
-
-TBinaryProtocol.prototype.readMessageEnd = function() {
-};
-
-TBinaryProtocol.prototype.readStructBegin = function() {
- return {fname: ''};
-};
-
-TBinaryProtocol.prototype.readStructEnd = function() {
-};
-
-TBinaryProtocol.prototype.readFieldBegin = function() {
- var type = this.readByte();
- if (type == Type.STOP) {
- return {fname: null, ftype: type, fid: 0};
- }
- var id = this.readI16();
- return {fname: null, ftype: type, fid: id};
-};
-
-TBinaryProtocol.prototype.readFieldEnd = function() {
-};
-
-TBinaryProtocol.prototype.readMapBegin = function() {
- var ktype = this.readByte();
- var vtype = this.readByte();
- var size = this.readI32();
- return {ktype: ktype, vtype: vtype, size: size};
-};
-
-TBinaryProtocol.prototype.readMapEnd = function() {
-};
-
-TBinaryProtocol.prototype.readListBegin = function() {
- var etype = this.readByte();
- var size = this.readI32();
- return {etype: etype, size: size};
-};
-
-TBinaryProtocol.prototype.readListEnd = function() {
-};
-
-TBinaryProtocol.prototype.readSetBegin = function() {
- var etype = this.readByte();
- var size = this.readI32();
- return {etype: etype, size: size};
-};
-
-TBinaryProtocol.prototype.readSetEnd = function() {
-};
-
-TBinaryProtocol.prototype.readBool = function() {
- var b = this.readByte();
- if (b === 0) {
- return false;
- }
- return true;
-};
-
-TBinaryProtocol.prototype.readByte = function() {
- return this.trans.readByte();
-};
-
-TBinaryProtocol.prototype.readI16 = function() {
- return this.trans.readI16();
-};
-
-TBinaryProtocol.prototype.readI32 = function() {
- return this.trans.readI32();
-};
-
-TBinaryProtocol.prototype.readI64 = function() {
- var buff = this.trans.read(8);
- return new Int64(buff);
-};
-
-TBinaryProtocol.prototype.readDouble = function() {
- return this.trans.readDouble();
-};
-
-TBinaryProtocol.prototype.readBinary = function() {
- var len = this.readI32();
- return this.trans.read(len);
-};
-
-TBinaryProtocol.prototype.readString = function() {
- var len = this.readI32();
- return this.trans.readString(len);
-};
-
-TBinaryProtocol.prototype.getTransport = function() {
- return this.trans;
-};
-
-TBinaryProtocol.prototype.skip = function(type) {
- switch (type) {
- case Type.STOP:
- return;
- case Type.BOOL:
- this.readBool();
- break;
- case Type.BYTE:
- this.readByte();
- break;
- case Type.I16:
- this.readI16();
- break;
- case Type.I32:
- this.readI32();
- break;
- case Type.I64:
- this.readI64();
- break;
- case Type.DOUBLE:
- this.readDouble();
- break;
- case Type.STRING:
- this.readString();
- break;
- case Type.STRUCT:
- this.readStructBegin();
- while (true) {
- var r = this.readFieldBegin();
- if (r.ftype === Type.STOP) {
- break;
- }
- this.skip(r.ftype);
- this.readFieldEnd();
- }
- this.readStructEnd();
- break;
- case Type.MAP:
- var mapBegin = this.readMapBegin();
- for (var i = 0; i < mapBegin.size; ++i) {
- this.skip(mapBegin.ktype);
- this.skip(mapBegin.vtype);
- }
- this.readMapEnd();
- break;
- case Type.SET:
- var setBegin = this.readSetBegin();
- for (var i2 = 0; i2 < setBegin.size; ++i2) {
- this.skip(setBegin.etype);
- }
- this.readSetEnd();
- break;
- case Type.LIST:
- var listBegin = this.readListBegin();
- for (var i3 = 0; i3 < listBegin.size; ++i3) {
- this.skip(listBegin.etype);
- }
- this.readListEnd();
- break;
- default:
- throw new Error("Invalid type: " + type);
- }
-};
-
-
-//
-// COMPACT PROTOCOL
-//
-///////////////////////////////////////////////////////////
-
-/**
- * Constructor Function for the Compact Protocol.
- * @constructor
- * @param {object} [trans] - The underlying transport to read/write.
- * @classdesc The Apache Thrift Protocol layer performs serialization
- * of base types, the compact protocol serializes data in binary
- * form with minimal space used for scalar values.
- */
-var TCompactProtocol = exports.TCompactProtocol = function(trans) {
- this.trans = trans;
- this.lastField_ = [];
- this.lastFieldId_ = 0;
- this.string_limit_ = 0;
- this.string_buf_ = null;
- this.string_buf_size_ = 0;
- this.container_limit_ = 0;
- this.booleanField_ = {
- name: null,
- hasBoolValue: false
- };
- this.boolValue_ = {
- hasBoolValue: false,
- boolValue: false
- };
-};
-
-
-//
-// Compact Protocol Constants
-//
-
-/**
- * Compact Protocol ID number.
- * @readonly
- * @const {number} PROTOCOL_ID
- */
-TCompactProtocol.PROTOCOL_ID = -126; //1000 0010
-
-/**
- * Compact Protocol version number.
- * @readonly
- * @const {number} VERSION_N
- */
-TCompactProtocol.VERSION_N = 1;
-
-/**
- * Compact Protocol version mask for combining protocol version and message type in one byte.
- * @readonly
- * @const {number} VERSION_MASK
- */
-TCompactProtocol.VERSION_MASK = 0x1f; //0001 1111
-
-/**
- * Compact Protocol message type mask for combining protocol version and message type in one byte.
- * @readonly
- * @const {number} TYPE_MASK
- */
-TCompactProtocol.TYPE_MASK = -32; //1110 0000
-
-/**
- * Compact Protocol message type bits for ensuring message type bit size.
- * @readonly
- * @const {number} TYPE_BITS
- */
-TCompactProtocol.TYPE_BITS = 7; //0000 0111
-
-/**
- * Compact Protocol message type shift amount for combining protocol version and message type in one byte.
- * @readonly
- * @const {number} TYPE_SHIFT_AMOUNT
- */
-TCompactProtocol.TYPE_SHIFT_AMOUNT = 5;
-
-/**
- * Compact Protocol type IDs used to keep type data within one nibble.
- * @readonly
- * @property {number} CT_STOP - End of a set of fields.
- * @property {number} CT_BOOLEAN_TRUE - Flag for Boolean field with true value (packed field and value).
- * @property {number} CT_BOOLEAN_FALSE - Flag for Boolean field with false value (packed field and value).
- * @property {number} CT_BYTE - Signed 8 bit integer.
- * @property {number} CT_I16 - Signed 16 bit integer.
- * @property {number} CT_I32 - Signed 32 bit integer.
- * @property {number} CT_I64 - Signed 64 bit integer (2^53 max in JavaScript).
- * @property {number} CT_DOUBLE - 64 bit IEEE 854 floating point.
- * @property {number} CT_BINARY - Array of bytes (used for strings also).
- * @property {number} CT_LIST - A collection type (unordered).
- * @property {number} CT_SET - A collection type (unordered and without repeated values).
- * @property {number} CT_MAP - A collection type (map/associative-array/dictionary).
- * @property {number} CT_STRUCT - A multifield type.
- */
-TCompactProtocol.Types = {
- CT_STOP: 0x00,
- CT_BOOLEAN_TRUE: 0x01,
- CT_BOOLEAN_FALSE: 0x02,
- CT_BYTE: 0x03,
- CT_I16: 0x04,
- CT_I32: 0x05,
- CT_I64: 0x06,
- CT_DOUBLE: 0x07,
- CT_BINARY: 0x08,
- CT_LIST: 0x09,
- CT_SET: 0x0A,
- CT_MAP: 0x0B,
- CT_STRUCT: 0x0C
-};
-
-/**
- * Array mapping Compact type IDs to standard Thrift type IDs.
- * @readonly
- */
-TCompactProtocol.TTypeToCType = [
- TCompactProtocol.Types.CT_STOP, // T_STOP
- 0, // unused
- TCompactProtocol.Types.CT_BOOLEAN_TRUE, // T_BOOL
- TCompactProtocol.Types.CT_BYTE, // T_BYTE
- TCompactProtocol.Types.CT_DOUBLE, // T_DOUBLE
- 0, // unused
- TCompactProtocol.Types.CT_I16, // T_I16
- 0, // unused
- TCompactProtocol.Types.CT_I32, // T_I32
- 0, // unused
- TCompactProtocol.Types.CT_I64, // T_I64
- TCompactProtocol.Types.CT_BINARY, // T_STRING
- TCompactProtocol.Types.CT_STRUCT, // T_STRUCT
- TCompactProtocol.Types.CT_MAP, // T_MAP
- TCompactProtocol.Types.CT_SET, // T_SET
- TCompactProtocol.Types.CT_LIST, // T_LIST
-];
-
-
-//
-// Compact Protocol Utilities
-//
-
-/**
- * Returns the underlying transport layer.
- * @return {object} The underlying transport layer.
- */TCompactProtocol.prototype.getTransport = function() {
- return this.trans;
-};
-
-/**
- * Lookup a Compact Protocol Type value for a given Thrift Type value.
- * N.B. Used only internally.
- * @param {number} ttype - Thrift type value
- * @returns {number} Compact protocol type value
- */
-TCompactProtocol.prototype.getCompactType = function(ttype) {
- return TCompactProtocol.TTypeToCType[ttype];
-};
-
-/**
- * Lookup a Thrift Type value for a given Compact Protocol Type value.
- * N.B. Used only internally.
- * @param {number} type - Compact Protocol type value
- * @returns {number} Thrift Type value
- */
-TCompactProtocol.prototype.getTType = function(type) {
- switch (type) {
- case Type.STOP:
- return Type.STOP;
- case TCompactProtocol.Types.CT_BOOLEAN_FALSE:
- case TCompactProtocol.Types.CT_BOOLEAN_TRUE:
- return Type.BOOL;
- case TCompactProtocol.Types.CT_BYTE:
- return Type.BYTE;
- case TCompactProtocol.Types.CT_I16:
- return Type.I16;
- case TCompactProtocol.Types.CT_I32:
- return Type.I32;
- case TCompactProtocol.Types.CT_I64:
- return Type.I64;
- case TCompactProtocol.Types.CT_DOUBLE:
- return Type.DOUBLE;
- case TCompactProtocol.Types.CT_BINARY:
- return Type.STRING;
- case TCompactProtocol.Types.CT_LIST:
- return Type.LIST;
- case TCompactProtocol.Types.CT_SET:
- return Type.SET;
- case TCompactProtocol.Types.CT_MAP:
- return Type.MAP;
- case TCompactProtocol.Types.CT_STRUCT:
- return Type.STRUCT;
- default:
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Unknown type: " + type);
- }
- return Type.STOP;
-};
-
-
-//
-// Compact Protocol write operations
-//
-
-/**
- * Send any buffered bytes to the end point.
- */
-TCompactProtocol.prototype.flush = function() {
- return this.trans.flush();
-};
-
-/**
- * Writes an RPC message header
- * @param {string} name - The method name for the message.
- * @param {number} type - The type of message (CALL, REPLY, EXCEPTION, ONEWAY).
- * @param {number} seqid - The call sequence number (if any).
- */
-TCompactProtocol.prototype.writeMessageBegin = function(name, type, seqid) {
- this.writeByte(TCompactProtocol.PROTOCOL_ID);
- this.writeByte((TCompactProtocol.VERSION_N & TCompactProtocol.VERSION_MASK) |
- ((type << TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_MASK));
- this.writeVarint32(seqid);
- this.writeString(name);
-};
-
-TCompactProtocol.prototype.writeMessageEnd = function() {
-};
-
-TCompactProtocol.prototype.writeStructBegin = function(name) {
- this.lastField_.push(this.lastFieldId_);
- this.lastFieldId_ = 0;
-};
-
-TCompactProtocol.prototype.writeStructEnd = function() {
- this.lastFieldId_ = this.lastField_.pop();
-};
-
-/**
- * Writes a struct field header
- * @param {string} name - The field name (not written with the compact protocol).
- * @param {number} type - The field data type (a normal Thrift field Type).
- * @param {number} id - The IDL field Id.
- */
-TCompactProtocol.prototype.writeFieldBegin = function(name, type, id) {
- if (type != Type.BOOL) {
- return this.writeFieldBeginInternal(name, type, id, -1);
- }
-
- this.booleanField_.name = name;
- this.booleanField_.fieldType = type;
- this.booleanField_.fieldId = id;
-};
-
-TCompactProtocol.prototype.writeFieldEnd = function() {
-};
-
-TCompactProtocol.prototype.writeFieldStop = function() {
- this.writeByte(TCompactProtocol.Types.CT_STOP);
-};
-
-/**
- * Writes a map collection header
- * @param {number} keyType - The Thrift type of the map keys.
- * @param {number} valType - The Thrift type of the map values.
- * @param {number} size - The number of k/v pairs in the map.
- */
-TCompactProtocol.prototype.writeMapBegin = function(keyType, valType, size) {
- if (size === 0) {
- this.writeByte(0);
- } else {
- this.writeVarint32(size);
- this.writeByte(this.getCompactType(keyType) << 4 | this.getCompactType(valType));
- }
-};
-
-TCompactProtocol.prototype.writeMapEnd = function() {
-};
-
-/**
- * Writes a list collection header
- * @param {number} elemType - The Thrift type of the list elements.
- * @param {number} size - The number of elements in the list.
- */
-TCompactProtocol.prototype.writeListBegin = function(elemType, size) {
- this.writeCollectionBegin(elemType, size);
-};
-
-TCompactProtocol.prototype.writeListEnd = function() {
-};
-
-/**
- * Writes a set collection header
- * @param {number} elemType - The Thrift type of the set elements.
- * @param {number} size - The number of elements in the set.
- */
-TCompactProtocol.prototype.writeSetBegin = function(elemType, size) {
- this.writeCollectionBegin(elemType, size);
-};
-
-TCompactProtocol.prototype.writeSetEnd = function() {
-};
-
-TCompactProtocol.prototype.writeBool = function(value) {
- if (this.booleanField_.name !== null) {
- // we haven't written the field header yet
- this.writeFieldBeginInternal(this.booleanField_.name,
- this.booleanField_.fieldType,
- this.booleanField_.fieldId,
- (value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE
- : TCompactProtocol.Types.CT_BOOLEAN_FALSE));
- this.booleanField_.name = null;
- } else {
- // we're not part of a field, so just write the value
- this.writeByte((value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE
- : TCompactProtocol.Types.CT_BOOLEAN_FALSE));
- }
-};
-
-TCompactProtocol.prototype.writeByte = function(b) {
- this.trans.write(new Buffer([b]));
-};
-
-TCompactProtocol.prototype.writeI16 = function(i16) {
- this.writeVarint32(this.i32ToZigzag(i16));
-};
-
-TCompactProtocol.prototype.writeI32 = function(i32) {
- this.writeVarint32(this.i32ToZigzag(i32));
-};
-
-TCompactProtocol.prototype.writeI64 = function(i64) {
- this.writeVarint64(this.i64ToZigzag(i64));
-};
-
-// Little-endian, unlike TBinaryProtocol
-TCompactProtocol.prototype.writeDouble = function(v) {
- var buff = new Buffer(8);
- var m, e, c;
-
- buff[7] = (v < 0 ? 0x80 : 0x00);
-
- v = Math.abs(v);
- if (v !== v) {
- // NaN, use QNaN IEEE format
- m = 2251799813685248;
- e = 2047;
- } else if (v === Infinity) {
- m = 0;
- e = 2047;
- } else {
- e = Math.floor(Math.log(v) / Math.LN2);
- c = Math.pow(2, -e);
- if (v * c < 1) {
- e--;
- c *= 2;
- }
-
- if (e + 1023 >= 2047)
- {
- // Overflow
- m = 0;
- e = 2047;
- }
- else if (e + 1023 >= 1)
- {
- // Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow
- m = (v*c-1) * POW_52;
- e += 1023;
- }
- else
- {
- // Denormalized - also catches the '0' case, somewhat by chance
- m = (v * POW_1022) * POW_52;
- e = 0;
- }
- }
-
- buff[6] = (e << 4) & 0xf0;
- buff[7] |= (e >> 4) & 0x7f;
-
- buff[0] = m & 0xff;
- m = Math.floor(m / POW_8);
- buff[1] = m & 0xff;
- m = Math.floor(m / POW_8);
- buff[2] = m & 0xff;
- m = Math.floor(m / POW_8);
- buff[3] = m & 0xff;
- m >>= 8;
- buff[4] = m & 0xff;
- m >>= 8;
- buff[5] = m & 0xff;
- m >>= 8;
- buff[6] |= m & 0x0f;
-
- this.trans.write(buff);
-};
-
-TCompactProtocol.prototype.writeString = function(arg) {
- this.writeBinary(arg);
-};
-
-TCompactProtocol.prototype.writeBinary = function(arg) {
- if (typeof arg === 'string') {
- this.writeVarint32(Buffer.byteLength(arg, 'utf8')) ;
- this.trans.write(arg, 'utf8');
- } else if (arg instanceof Buffer) {
- this.writeVarint32(arg.length);
- this.trans.write(arg);
- } else {
- throw new Error('writeString/writeBinary called without a string/Buffer argument: ' + arg);
- }
-};
-
-
-//
-// Compact Protocol internal write methods
-//
-
-TCompactProtocol.prototype.writeFieldBeginInternal = function(name,
- fieldType,
- fieldId,
- typeOverride) {
- //If there's a type override, use that.
- var typeToWrite = (typeOverride == -1 ? this.getCompactType(fieldType) : typeOverride);
- //Check if we can delta encode the field id
- if (fieldId > this.lastFieldId_ && fieldId - this.lastFieldId_ <= 15) {
- //Include the type delta with the field ID
- this.writeByte((fieldId - this.lastFieldId_) << 4 | typeToWrite);
- } else {
- //Write separate type and ID values
- this.writeByte(typeToWrite);
- this.writeI16(fieldId);
- }
- this.lastFieldId_ = fieldId;
-};
-
-TCompactProtocol.prototype.writeCollectionBegin = function(elemType, size) {
- if (size <= 14) {
- //Combine size and type in one byte if possible
- this.writeByte(size << 4 | this.getCompactType(elemType));
- } else {
- this.writeByte(0xf0 | this.getCompactType(elemType));
- this.writeVarint32(size);
- }
-};
-
-/**
- * Write an i32 as a varint. Results in 1-5 bytes on the wire.
- */
-TCompactProtocol.prototype.writeVarint32 = function(n) {
- var buf = new Buffer(5);
- var wsize = 0;
- while (true) {
- if ((n & ~0x7F) === 0) {
- buf[wsize++] = n;
- break;
- } else {
- buf[wsize++] = ((n & 0x7F) | 0x80);
- n = n >>> 7;
- }
- }
- var wbuf = new Buffer(wsize);
- buf.copy(wbuf,0,0,wsize);
- this.trans.write(wbuf);
-};
-
-/**
- * Write an i64 as a varint. Results in 1-10 bytes on the wire.
- * N.B. node-int64 is always big endian
- */
-TCompactProtocol.prototype.writeVarint64 = function(n) {
- if (typeof n === "number"){
- n = new Int64(n);
- }
- if (! (n instanceof Int64)) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Expected Int64 or Number, found: " + n);
- }
-
- var buf = new Buffer(10);
- var wsize = 0;
- var hi = n.buffer.readUInt32BE(0, true);
- var lo = n.buffer.readUInt32BE(4, true);
- var mask = 0;
- while (true) {
- if (((lo & ~0x7F) === 0) && (hi === 0)) {
- buf[wsize++] = lo;
- break;
- } else {
- buf[wsize++] = ((lo & 0x7F) | 0x80);
- mask = hi << 25;
- lo = lo >>> 7;
- hi = hi >>> 7;
- lo = lo | mask;
- }
- }
- var wbuf = new Buffer(wsize);
- buf.copy(wbuf,0,0,wsize);
- this.trans.write(wbuf);
-};
-
-/**
- * Convert l into a zigzag long. This allows negative numbers to be
- * represented compactly as a varint.
- */
-TCompactProtocol.prototype.i64ToZigzag = function(l) {
- if (typeof l === 'string') {
- l = new Int64(parseInt(l, 10));
- } else if (typeof l === 'number') {
- l = new Int64(l);
- }
- if (! (l instanceof Int64)) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Expected Int64 or Number, found: " + l);
- }
- var hi = l.buffer.readUInt32BE(0, true);
- var lo = l.buffer.readUInt32BE(4, true);
- var sign = hi >>> 31;
- hi = ((hi << 1) | (lo >>> 31)) ^ ((!!sign) ? 0xFFFFFFFF : 0);
- lo = (lo << 1) ^ ((!!sign) ? 0xFFFFFFFF : 0);
- return new Int64(hi, lo);
-};
-
-/**
- * Convert n into a zigzag int. This allows negative numbers to be
- * represented compactly as a varint.
- */
-TCompactProtocol.prototype.i32ToZigzag = function(n) {
- return (n << 1) ^ ((n & 0x80000000) ? 0xFFFFFFFF : 0);
-};
-
-
-//
-// Compact Protocol read operations
-//
-
-TCompactProtocol.prototype.readMessageBegin = function() {
- //Read protocol ID
- var protocolId = this.trans.readByte();
- if (protocolId != TCompactProtocol.PROTOCOL_ID) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad protocol identifier " + protocolId);
- }
-
- //Read Version and Type
- var versionAndType = this.trans.readByte();
- var version = (versionAndType & TCompactProtocol.VERSION_MASK);
- if (version != TCompactProtocol.VERSION_N) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad protocol version " + version);
- }
- var type = ((versionAndType >> TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_BITS);
-
- //Read SeqId
- var seqid = this.readVarint32();
-
- //Read name
- var name = this.readString();
-
- return {fname: name, mtype: type, rseqid: seqid};
-};
-
-TCompactProtocol.prototype.readMessageEnd = function() {
-};
-
-TCompactProtocol.prototype.readStructBegin = function() {
- this.lastField_.push(this.lastFieldId_);
- this.lastFieldId_ = 0;
- return {fname: ''};
-};
-
-TCompactProtocol.prototype.readStructEnd = function() {
- this.lastFieldId_ = this.lastField_.pop();
-};
-
-TCompactProtocol.prototype.readFieldBegin = function() {
- var fieldId = 0;
- var b = this.trans.readByte(b);
- var type = (b & 0x0f);
-
- if (type == TCompactProtocol.Types.CT_STOP) {
- return {fname: null, ftype: Thrift.Type.STOP, fid: 0};
- }
-
- //Mask off the 4 MSB of the type header to check for field id delta.
- var modifier = ((b & 0x000000f0) >>> 4);
- if (modifier === 0) {
- //If not a delta read the field id.
- fieldId = this.readI16();
- } else {
- //Recover the field id from the delta
- fieldId = (this.lastFieldId_ + modifier);
- }
- var fieldType = this.getTType(type);
-
- //Boolean are encoded with the type
- if (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE ||
- type == TCompactProtocol.Types.CT_BOOLEAN_FALSE) {
- this.boolValue_.hasBoolValue = true;
- this.boolValue_.boolValue =
- (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE ? true : false);
- }
-
- //Save the new field for the next delta computation.
- this.lastFieldId_ = fieldId;
- return {fname: null, ftype: fieldType, fid: fieldId};
-};
-
-TCompactProtocol.prototype.readFieldEnd = function() {
-};
-
-TCompactProtocol.prototype.readMapBegin = function() {
- var msize = this.readVarint32();
- if (msize < 0) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative map size");
- }
-
- var kvType = 0;
- if (msize !== 0) {
- kvType = this.trans.readByte();
- }
-
- var keyType = this.getTType((kvType & 0xf0) >>> 4);
- var valType = this.getTType(kvType & 0xf);
- return {ktype: keyType, vtype: valType, size: msize};
-};
-
-TCompactProtocol.prototype.readMapEnd = function() {
-};
-
-TCompactProtocol.prototype.readListBegin = function() {
- var size_and_type = this.trans.readByte();
-
- var lsize = (size_and_type >>> 4) & 0x0000000f;
- if (lsize == 15) {
- lsize = this.readVarint32();
- }
-
- if (lsize < 0) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative list size");
- }
-
- var elemType = this.getTType(size_and_type & 0x0000000f);
-
- return {etype: elemType, size: lsize};
-};
-
-TCompactProtocol.prototype.readListEnd = function() {
-};
-
-TCompactProtocol.prototype.readSetBegin = function() {
- return this.readListBegin();
-};
-
-TCompactProtocol.prototype.readSetEnd = function() {
-};
-
-TCompactProtocol.prototype.readBool = function() {
- var value = false;
- var rsize = 0;
- if (this.boolValue_.hasBoolValue === true) {
- value = this.boolValue_.boolValue;
- this.boolValue_.hasBoolValue = false;
- } else {
- var res = this.trans.readByte();
- rsize = res.rsize;
- value = (res.value == TCompactProtocol.Types.CT_BOOLEAN_TRUE);
- }
- return value;
-};
-
-TCompactProtocol.prototype.readByte = function() {
- return this.trans.readByte();
-};
-
-TCompactProtocol.prototype.readI16 = function() {
- return this.readI32();
-};
-
-TCompactProtocol.prototype.readI32 = function() {
- return this.zigzagToI32(this.readVarint32());
-};
-
-TCompactProtocol.prototype.readI64 = function() {
- return this.zigzagToI64(this.readVarint64());
-};
-
-// Little-endian, unlike TBinaryProtocol
-TCompactProtocol.prototype.readDouble = function() {
- var buff = this.trans.read(8);
- var off = 0;
-
- var signed = buff[off + 7] & 0x80;
- var e = (buff[off+6] & 0xF0) >> 4;
- e += (buff[off+7] & 0x7F) << 4;
-
- var m = buff[off];
- m += buff[off+1] << 8;
- m += buff[off+2] << 16;
- m += buff[off+3] * POW_24;
- m += buff[off+4] * POW_32;
- m += buff[off+5] * POW_40;
- m += (buff[off+6] & 0x0F) * POW_48;
-
- switch (e) {
- case 0:
- e = -1022;
- break;
- case 2047:
- return m ? NaN : (signed ? -Infinity : Infinity);
- default:
- m += POW_52;
- e -= 1023;
- }
-
- if (signed) {
- m *= -1;
- }
-
- return m * Math.pow(2, e - 52);
-};
-
-TCompactProtocol.prototype.readBinary = function() {
- var size = this.readVarint32();
- // Catch empty string case
- if (size === 0) {
- return "";
- }
-
- // Catch error cases
- if (size < 0) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative binary/string size");
- }
- var value = this.trans.readString(size);
-
- return value;
-};
-
-TCompactProtocol.prototype.readString = function() {
- return this.readBinary();
-};
-
-
-//
-// Compact Protocol internal read operations
-//
-
-/**
- * Read an i32 from the wire as a varint. The MSB of each byte is set
- * if there is another byte to follow. This can read up to 5 bytes.
- */
-TCompactProtocol.prototype.readVarint32 = function() {
- return this.readVarint64();
-};
-
-/**
- * Read an i64 from the wire as a proper varint. The MSB of each byte is set
- * if there is another byte to follow. This can read up to 10 bytes.
- */
-TCompactProtocol.prototype.readVarint64 = function() {
- var rsize = 0;
- var lo = 0;
- var hi = 0;
- var shift = 0;
- while (true) {
- var b = this.trans.readByte();
- rsize ++;
- if (shift <= 25) {
- lo = lo | ((b & 0x7f) << shift);
- } else if (25 < shift && shift < 32) {
- lo = lo | ((b & 0x7f) << shift);
- hi = hi | ((b & 0x7f) >>> (32-shift));
- } else {
- hi = hi | ((b & 0x7f) << (shift-32));
- }
- shift += 7;
- if (!(b & 0x80)) {
- break;
- }
- if (rsize >= 10) {
- throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Variable-length int over 10 bytes.");
- }
- }
- var i64 = new Int64(hi, lo);
- return i64.toNumber();
-};
-
-/**
- * Convert from zigzag int to int.
- */
-TCompactProtocol.prototype.zigzagToI32 = function(n) {
- return (n >>> 1) ^ (-1 * (n & 1));
-};
-
-/**
- * Convert from zigzag long to long.
- */
-TCompactProtocol.prototype.zigzagToI64 = function(n) {
- var zz = new Int64(n);
- var hi = zz.buffer.readUInt32BE(0, true);
- var lo = zz.buffer.readUInt32BE(4, true);
-
- var neg = new Int64(hi & 0, lo & 1);
- neg._2scomp();
- var hi_neg = neg.buffer.readUInt32BE(0, true);
- var lo_neg = neg.buffer.readUInt32BE(4, true);
-
- var hi_lo = (hi << 31);
- hi = (hi >>> 1) ^ (hi_neg);
- lo = ((lo >>> 1) | hi_lo) ^ (lo_neg);
- var i64 = new Int64(hi, lo);
- return i64.toNumber();
-};
-
-TCompactProtocol.prototype.skip = function(type) {
- switch (type) {
- case Type.STOP:
- return;
- case Type.BOOL:
- this.readBool();
- break;
- case Type.BYTE:
- this.readByte();
- break;
- case Type.I16:
- this.readI16();
- break;
- case Type.I32:
- this.readI32();
- break;
- case Type.I64:
- this.readI64();
- break;
- case Type.DOUBLE:
- this.readDouble();
- break;
- case Type.STRING:
- this.readString();
- break;
- case Type.STRUCT:
- this.readStructBegin();
- while (true) {
- var r = this.readFieldBegin();
- if (r.ftype === Type.STOP) {
- break;
- }
- this.skip(r.ftype);
- this.readFieldEnd();
- }
- this.readStructEnd();
- break;
- case Type.MAP:
- var mapBegin = this.readMapBegin();
- for (var i = 0; i < mapBegin.size; ++i) {
- this.skip(mapBegin.ktype);
- this.skip(mapBegin.vtype);
- }
- this.readMapEnd();
- break;
- case Type.SET:
- var setBegin = this.readSetBegin();
- for (var i2 = 0; i2 < setBegin.size; ++i2) {
- this.skip(setBegin.etype);
- }
- this.readSetEnd();
- break;
- case Type.LIST:
- var listBegin = this.readListBegin();
- for (var i3 = 0; i3 < listBegin.size; ++i3) {
- this.skip(listBegin.etype);
- }
- this.readListEnd();
- break;
- default:
- throw new Error("Invalid type: " + type);
- }
-};
-
-
-//
-// JSON PROTOCOL
-//
-///////////////////////////////////////////////////////////
-
-var TJSONProtocol = exports.TJSONProtocol = function(trans) {
- this.trans = trans;
-};
-
-TJSONProtocol.Type = {};
-TJSONProtocol.Type[Thrift.Type.BOOL] = '"tf"';
-TJSONProtocol.Type[Thrift.Type.BYTE] = '"i8"';
-TJSONProtocol.Type[Thrift.Type.I16] = '"i16"';
-TJSONProtocol.Type[Thrift.Type.I32] = '"i32"';
-TJSONProtocol.Type[Thrift.Type.I64] = '"i64"';
-TJSONProtocol.Type[Thrift.Type.DOUBLE] = '"dbl"';
-TJSONProtocol.Type[Thrift.Type.STRUCT] = '"rec"';
-TJSONProtocol.Type[Thrift.Type.STRING] = '"str"';
-TJSONProtocol.Type[Thrift.Type.MAP] = '"map"';
-TJSONProtocol.Type[Thrift.Type.LIST] = '"lst"';
-TJSONProtocol.Type[Thrift.Type.SET] = '"set"';
-
-
-TJSONProtocol.RType = {};
-TJSONProtocol.RType.tf = Thrift.Type.BOOL;
-TJSONProtocol.RType.i8 = Thrift.Type.BYTE;
-TJSONProtocol.RType.i16 = Thrift.Type.I16;
-TJSONProtocol.RType.i32 = Thrift.Type.I32;
-TJSONProtocol.RType.i64 = Thrift.Type.I64;
-TJSONProtocol.RType.dbl = Thrift.Type.DOUBLE;
-TJSONProtocol.RType.rec = Thrift.Type.STRUCT;
-TJSONProtocol.RType.str = Thrift.Type.STRING;
-TJSONProtocol.RType.map = Thrift.Type.MAP;
-TJSONProtocol.RType.lst = Thrift.Type.LIST;
-TJSONProtocol.RType.set = Thrift.Type.SET;
-
-TJSONProtocol.Version = 1;
-
-TJSONProtocol.prototype.flush = function() {
- return this.trans.flush();
-};
-
-TJSONProtocol.prototype.writeMessageBegin = function(name, messageType, seqid) {
- this.tstack = [];
- this.tpos = [];
-
- this.tstack.push([TJSONProtocol.Version, '"' + name + '"', messageType, seqid]);
-};
-
-TJSONProtocol.prototype.writeMessageEnd = function() {
- var obj = this.tstack.pop();
-
- this.wobj = this.tstack.pop();
- this.wobj.push(obj);
-
- this.wbuf = '[' + this.wobj.join(',') + ']';
-
- this.trans.write(this.wbuf);
-};
-
-TJSONProtocol.prototype.writeStructBegin = function(name) {
- this.tpos.push(this.tstack.length);
- this.tstack.push({});
-};
-
-TJSONProtocol.prototype.writeStructEnd = function() {
- var p = this.tpos.pop();
- var struct = this.tstack[p];
- var str = '{';
- var first = true;
- for (var key in struct) {
- if (first) {
- first = false;
- } else {
- str += ',';
- }
-
- str += key + ':' + struct[key];
- }
-
- str += '}';
- this.tstack[p] = str;
-};
-
-TJSONProtocol.prototype.writeFieldBegin = function(name, fieldType, fieldId) {
- this.tpos.push(this.tstack.length);
- this.tstack.push({ 'fieldId': '"' +
- fieldId + '"', 'fieldType': TJSONProtocol.Type[fieldType]
- });
-};
-
-TJSONProtocol.prototype.writeFieldEnd = function() {
- var value = this.tstack.pop();
- var fieldInfo = this.tstack.pop();
-
- if (':' + value === ":[object Object]") {
- this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
- fieldInfo.fieldType + ':' + JSON.stringify(value) + '}';
- } else {
- this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
- fieldInfo.fieldType + ':' + value + '}';
- }
- this.tpos.pop();
-};
-
-TJSONProtocol.prototype.writeFieldStop = function() {
-};
-
-TJSONProtocol.prototype.writeMapBegin = function(ktype, vtype, size) {
- //size is invalid, we'll set it on end.
- this.tpos.push(this.tstack.length);
- this.tstack.push([TJSONProtocol.Type[ktype], TJSONProtocol.Type[vtype], 0]);
-};
-
-TJSONProtocol.prototype.writeMapEnd = function() {
- var p = this.tpos.pop();
-
- if (p == this.tstack.length) {
- return;
- }
-
- if ((this.tstack.length - p - 1) % 2 !== 0) {
- this.tstack.push('');
- }
-
- var size = (this.tstack.length - p - 1) / 2;
-
- this.tstack[p][this.tstack[p].length - 1] = size;
-
- var map = '}';
- var first = true;
- while (this.tstack.length > p + 1) {
- var v = this.tstack.pop();
- var k = this.tstack.pop();
- if (first) {
- first = false;
- } else {
- map = ',' + map;
- }
-
- if (! isNaN(k)) { k = '"' + k + '"'; } //json "keys" need to be strings
- map = k + ':' + v + map;
- }
- map = '{' + map;
-
- this.tstack[p].push(map);
- this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
-};
-
-TJSONProtocol.prototype.writeListBegin = function(etype, size) {
- this.tpos.push(this.tstack.length);
- this.tstack.push([TJSONProtocol.Type[etype], size]);
-};
-
-TJSONProtocol.prototype.writeListEnd = function() {
- var p = this.tpos.pop();
-
- while (this.tstack.length > p + 1) {
- var tmpVal = this.tstack[p + 1];
- this.tstack.splice(p + 1, 1);
- this.tstack[p].push(tmpVal);
- }
-
- this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
-};
-
-TJSONProtocol.prototype.writeSetBegin = function(etype, size) {
- this.tpos.push(this.tstack.length);
- this.tstack.push([TJSONProtocol.Type[etype], size]);
-};
-
-TJSONProtocol.prototype.writeSetEnd = function() {
- var p = this.tpos.pop();
-
- while (this.tstack.length > p + 1) {
- var tmpVal = this.tstack[p + 1];
- this.tstack.splice(p + 1, 1);
- this.tstack[p].push(tmpVal);
- }
-
- this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
-};
-
-TJSONProtocol.prototype.writeBool = function(bool) {
- this.tstack.push(bool ? 1 : 0);
-};
-
-TJSONProtocol.prototype.writeByte = function(byte) {
- this.tstack.push(byte);
-};
-
-TJSONProtocol.prototype.writeI16 = function(i16) {
- this.tstack.push(i16);
-};
-
-TJSONProtocol.prototype.writeI32 = function(i32) {
- this.tstack.push(i32);
-};
-
-TJSONProtocol.prototype.writeI64 = function(i64) {
- this.tstack.push(i64);
-};
-
-TJSONProtocol.prototype.writeDouble = function(dub) {
- this.tstack.push(dub);
-};
-
-TJSONProtocol.prototype.writeString = function(str) {
- // We do not encode uri components for wire transfer:
- if (str === null) {
- this.tstack.push(null);
- } else {
- // concat may be slower than building a byte buffer
- var escapedString = '';
- for (var i = 0; i < str.length; i++) {
- var ch = str.charAt(i); // a single double quote: "
- if (ch === '\"') {
- escapedString += '\\\"'; // write out as: \"
- } else if (ch === '\\') { // a single backslash: \
- escapedString += '\\\\'; // write out as: \\
- /* Currently escaped forward slashes break TJSONProtocol.
- * As it stands, we can simply pass forward slashes into
- * our strings across the wire without being escaped.
- * I think this is the protocol's bug, not thrift.js
- * } else if(ch === '/') { // a single forward slash: /
- * escapedString += '\\/'; // write out as \/
- * }
- */
- } else if (ch === '\b') { // a single backspace: invisible
- escapedString += '\\b'; // write out as: \b"
- } else if (ch === '\f') { // a single formfeed: invisible
- escapedString += '\\f'; // write out as: \f"
- } else if (ch === '\n') { // a single newline: invisible
- escapedString += '\\n'; // write out as: \n"
- } else if (ch === '\r') { // a single return: invisible
- escapedString += '\\r'; // write out as: \r"
- } else if (ch === '\t') { // a single tab: invisible
- escapedString += '\\t'; // write out as: \t"
- } else {
- escapedString += ch; // Else it need not be escaped
- }
- }
- this.tstack.push('"' + escapedString + '"');
- }
-};
-
-TJSONProtocol.prototype.writeBinary = function(arg) {
- this.writeString(arg);
-};
-
-TJSONProtocol.prototype.readMessageBegin = function() {
- this.rstack = [];
- this.rpos = [];
-
- //Borrow the inbound transport buffer and ensure data is present/consistent
- var transBuf = this.trans.borrow();
- if (transBuf.readIndex >= transBuf.writeIndex) {
- throw new InputBufferUnderrunError();
- }
- var cursor = transBuf.readIndex;
-
- if (transBuf.buf[cursor] !== 0x5B) { //[
- throw new Error("Malformed JSON input, no opening bracket");
- }
-
- //Parse a single message (there may be several in the buffer)
- // TODO: Handle characters using multiple code units
- cursor++;
- var openBracketCount = 1;
- var inString = false;
- for (; cursor < transBuf.writeIndex; cursor++) {
- var chr = transBuf.buf[cursor];
- //we use hexa charcode here because data[i] returns an int and not a char
- if (inString) {
- if (chr === 0x22) { //"
- inString = false;
- } else if (chr === 0x5C) { //\
- //escaped character, skip
- cursor += 1;
- }
- } else {
- if (chr === 0x5B) { //[
- openBracketCount += 1;
- } else if (chr === 0x5D) { //]
- openBracketCount -= 1;
- if (openBracketCount === 0) {
- //end of json message detected
- break;
- }
- } else if (chr === 0x22) { //"
- inString = true;
- }
- }
- }
-
- if (openBracketCount !== 0) {
- throw new Error("Malformed JSON input, mismatched backets");
- }
-
- //Reconstitute the JSON object and conume the necessary bytes
- this.robj = JSON.parse(transBuf.buf.slice(transBuf.readIndex, cursor+1));
- this.trans.consume(cursor + 1 - transBuf.readIndex);
-
- //Verify the protocol version
- var version = this.robj.shift();
- if (version != TJSONProtocol.Version) {
- throw 'Wrong thrift protocol version: ' + version;
- }
-
- //Objectify the thrift message {name/type/sequence-number} for return
- // and then save the JSON object in rstack
- var r = {};
- r.fname = this.robj.shift();
- r.mtype = this.robj.shift();
- r.rseqid = this.robj.shift();
- this.rstack.push(this.robj.shift());
- return r;
-};
-
-TJSONProtocol.prototype.readMessageEnd = function() {
-};
-
-TJSONProtocol.prototype.readStructBegin = function() {
- var r = {};
- r.fname = '';
-
- //incase this is an array of structs
- if (this.rstack[this.rstack.length - 1] instanceof Array) {
- this.rstack.push(this.rstack[this.rstack.length - 1].shift());
- }
-
- return r;
-};
-
-TJSONProtocol.prototype.readStructEnd = function() {
- this.rstack.pop();
-};
-
-TJSONProtocol.prototype.readFieldBegin = function() {
- var r = {};
-
- var fid = -1;
- var ftype = Thrift.Type.STOP;
-
- //get a fieldId
- for (var f in (this.rstack[this.rstack.length - 1])) {
- if (f === null) {
- continue;
- }
-
- fid = parseInt(f, 10);
- this.rpos.push(this.rstack.length);
-
- var field = this.rstack[this.rstack.length - 1][fid];
-
- //remove so we don't see it again
- delete this.rstack[this.rstack.length - 1][fid];
-
- this.rstack.push(field);
-
- break;
- }
-
- if (fid != -1) {
- //should only be 1 of these but this is the only
- //way to match a key
- for (var i in (this.rstack[this.rstack.length - 1])) {
- if (TJSONProtocol.RType[i] === null) {
- continue;
- }
-
- ftype = TJSONProtocol.RType[i];
- this.rstack[this.rstack.length - 1] = this.rstack[this.rstack.length - 1][i];
- }
- }
-
- r.fname = '';
- r.ftype = ftype;
- r.fid = fid;
-
- return r;
-};
-
-TJSONProtocol.prototype.readFieldEnd = function() {
- var pos = this.rpos.pop();
-
- //get back to the right place in the stack
- while (this.rstack.length > pos) {
- this.rstack.pop();
- }
-};
-
-TJSONProtocol.prototype.readMapBegin = function() {
- var map = this.rstack.pop();
-
- var r = {};
- r.ktype = TJSONProtocol.RType[map.shift()];
- r.vtype = TJSONProtocol.RType[map.shift()];
- r.size = map.shift();
-
-
- this.rpos.push(this.rstack.length);
- this.rstack.push(map.shift());
-
- return r;
-};
-
-TJSONProtocol.prototype.readMapEnd = function() {
- this.readFieldEnd();
-};
-
-TJSONProtocol.prototype.readListBegin = function() {
- var list = this.rstack[this.rstack.length - 1];
-
- var r = {};
- r.etype = TJSONProtocol.RType[list.shift()];
- r.size = list.shift();
-
- this.rpos.push(this.rstack.length);
- this.rstack.push(list);
-
- return r;
-};
-
-TJSONProtocol.prototype.readListEnd = function() {
- this.readFieldEnd();
-};
-
-TJSONProtocol.prototype.readSetBegin = function() {
- return this.readListBegin();
-};
-
-TJSONProtocol.prototype.readSetEnd = function() {
- return this.readListEnd();
-};
-
-TJSONProtocol.prototype.readBool = function() {
- var r = this.readI32();
-
- if (r !== null && r.value == '1') {
- r.value = true;
- } else {
- r.value = false;
- }
-
- return r;
-};
-
-TJSONProtocol.prototype.readByte = function() {
- return this.readI32();
-};
-
-TJSONProtocol.prototype.readI16 = function() {
- return this.readI32();
-};
-
-TJSONProtocol.prototype.readI32 = function(f) {
- if (f === undefined) {
- f = this.rstack[this.rstack.length - 1];
- }
-
- var r = {};
-
- if (f instanceof Array) {
- if (f.length === 0) {
- r.value = undefined;
- } else {
- r.value = f.shift();
- }
- } else if (f instanceof Object) {
- for (var i in f) {
- if (i === null) {
- continue;
- }
- this.rstack.push(f[i]);
- delete f[i];
-
- r.value = i;
- break;
- }
- } else {
- r.value = f;
- this.rstack.pop();
- }
-
- return r.value;
-};
-
-TJSONProtocol.prototype.readI64 = function() {
- return new Int64(this.readI32());
-};
-
-TJSONProtocol.prototype.readDouble = function() {
- return this.readI32();
-};
-
-TJSONProtocol.prototype.readBinary = function() {
- return this.readString();
-};
-
-TJSONProtocol.prototype.readString = function() {
- var r = this.readI32();
- return r;
-};
-
-TJSONProtocol.prototype.getTransport = function() {
- return this.trans;
-};
-
-//Method to arbitrarily skip over data.
-TJSONProtocol.prototype.skip = function(type) {
- throw 'skip not supported yet';
-};
+module.exports.TBinaryProtocol = require('./binary_protocol');
+module.exports.TCompactProtocol = require('./compact_protocol');
+module.exports.TJSONProtocol = require('./json_protocol');
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/server.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/server.js b/lib/nodejs/lib/thrift/server.js
index 8715f2c..921bb86 100644
--- a/lib/nodejs/lib/thrift/server.js
+++ b/lib/nodejs/lib/thrift/server.js
@@ -19,9 +19,9 @@
var net = require('net');
var tls = require('tls');
-var ttransport = require('./transport'),
- TBinaryProtocol = require('./protocol').TBinaryProtocol;
-
+var TBufferedTransport = require('./buffered_transport');
+var TBinaryProtocol = require('./binary_protocol');
+var InputBufferUnderrunError = require('./input_buffer_underrun_error');
/**
* Create a Thrift server which can serve one or multiple services.
@@ -31,13 +31,13 @@ var ttransport = require('./transport'),
* @returns {object} - The Apache Thrift Multiplex Server.
*/
exports.createMultiplexServer = function(processor, options) {
- var transport = (options && options.transport) ? options.transport : ttransport.TBufferedTransport;
+ var transport = (options && options.transport) ? options.transport : TBufferedTransport;
var protocol = (options && options.protocol) ? options.protocol : TBinaryProtocol;
function serverImpl(stream) {
var self = this;
- stream.on('error', function(err) {
- self.emit('error', err);
+ stream.on('error', function(err) {
+ self.emit('error', err);
});
stream.on('data', transport.receiver(function(transportWithData) {
var input = new protocol(transportWithData);
@@ -56,7 +56,7 @@ exports.createMultiplexServer = function(processor, options) {
transportWithData.commitPosition();
} while (true);
} catch (err) {
- if (err instanceof ttransport.InputBufferUnderrunError) {
+ if (err instanceof InputBufferUnderrunError) {
//The last data in the buffer was not a complete message, wait for the rest
transportWithData.rollbackPosition();
}
http://git-wip-us.apache.org/repos/asf/thrift/blob/96f4f07b/lib/nodejs/lib/thrift/transport.js
----------------------------------------------------------------------
diff --git a/lib/nodejs/lib/thrift/transport.js b/lib/nodejs/lib/thrift/transport.js
index 6d4224a..59daa98 100644
--- a/lib/nodejs/lib/thrift/transport.js
+++ b/lib/nodejs/lib/thrift/transport.js
@@ -16,285 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-var emptyBuf = new Buffer(0);
-var binary = require('./binary');
-var util = require("util");
-
-var InputBufferUnderrunError = exports.InputBufferUnderrunError = function(message) {
- Error.call(this, message);
-};
-util.inherits(InputBufferUnderrunError, Error);
-
-var TFramedTransport = exports.TFramedTransport = function(buffer, callback) {
- this.inBuf = buffer || emptyBuf;
- this.outBuffers = [];
- this.outCount = 0;
- this.readPos = 0;
- this.onFlush = callback;
-};
-TFramedTransport.receiver = function(callback) {
- var residual = null;
-
- return function(data) {
- // Prepend any residual data from our previous read
- if (residual) {
- data = Buffer.concat([residual, data]);
- residual = null;
- }
-
- // framed transport
- while (data.length) {
- if (data.length < 4) {
- // Not enough bytes to continue, save and resume on next packet
- residual = data;
- return;
- }
- var frameSize = binary.readI32(data, 0);
- if (data.length < 4 + frameSize) {
- // Not enough bytes to continue, save and resume on next packet
- residual = data;
- return;
- }
-
- var frame = data.slice(4, 4 + frameSize);
- residual = data.slice(4 + frameSize);
-
- callback(new TFramedTransport(frame));
-
- data = residual;
- residual = null;
- }
- };
-};
-
-TFramedTransport.prototype = {
- commitPosition: function(){},
- rollbackPosition: function(){},
-
- // TODO: Implement open/close support
- isOpen: function() {return true;},
- open: function() {},
- close: function() {},
-
- ensureAvailable: function(len) {
- if (this.readPos + len > this.inBuf.length) {
- throw new InputBufferUnderrunError();
- }
- },
-
- read: function(len) { // this function will be used for each frames.
- this.ensureAvailable(len);
- var end = this.readPos + len;
-
- if (this.inBuf.length < end) {
- throw new Error('read(' + len + ') failed - not enough data');
- }
-
- var buf = this.inBuf.slice(this.readPos, end);
- this.readPos = end;
- return buf;
- },
-
- readByte: function() {
- this.ensureAvailable(1);
- return binary.readByte(this.inBuf[this.readPos++]);
- },
-
- readI16: function() {
- this.ensureAvailable(2);
- var i16 = binary.readI16(this.inBuf, this.readPos);
- this.readPos += 2;
- return i16;
- },
-
- readI32: function() {
- this.ensureAvailable(4);
- var i32 = binary.readI32(this.inBuf, this.readPos);
- this.readPos += 4;
- return i32;
- },
-
- readDouble: function() {
- this.ensureAvailable(8);
- var d = binary.readDouble(this.inBuf, this.readPos);
- this.readPos += 8;
- return d;
- },
-
- readString: function(len) {
- this.ensureAvailable(len);
- var str = this.inBuf.toString('utf8', this.readPos, this.readPos + len);
- this.readPos += len;
- return str;
- },
-
- borrow: function() {
- return { buf: this.inBuf, readIndex: this.readPos, writeIndex: this.inBuf.length };
- },
-
- consume: function(bytesConsumed) {
- this.readPos += bytesConsumed;
- },
-
- write: function(buf, encoding) {
- if (typeof(buf) === "string") {
- buf = new Buffer(buf, encoding || 'utf8');
- }
- this.outBuffers.push(buf);
- this.outCount += buf.length;
- },
-
- flush: function() {
- var out = new Buffer(this.outCount),
- pos = 0;
- this.outBuffers.forEach(function(buf) {
- buf.copy(out, pos, 0);
- pos += buf.length;
- });
-
- if (this.onFlush) {
- // TODO: optimize this better, allocate one buffer instead of both:
- var msg = new Buffer(out.length + 4);
- binary.writeI32(msg, out.length);
- out.copy(msg, 4, 0, out.length);
- this.onFlush(msg);
- }
-
- this.outBuffers = [];
- this.outCount = 0;
- }
-};
-
-var TBufferedTransport = exports.TBufferedTransport = function(buffer, callback) {
- this.defaultReadBufferSize = 1024;
- this.writeBufferSize = 512; // Soft Limit
- this.inBuf = new Buffer(this.defaultReadBufferSize);
- this.readCursor = 0;
- this.writeCursor = 0; // for input buffer
- this.outBuffers = [];
- this.outCount = 0;
- this.onFlush = callback;
-};
-TBufferedTransport.receiver = function(callback) {
- var reader = new TBufferedTransport();
-
- return function(data) {
- if (reader.writeCursor + data.length > reader.inBuf.length) {
- var buf = new Buffer(reader.writeCursor + data.length);
- reader.inBuf.copy(buf, 0, 0, reader.writeCursor);
- reader.inBuf = buf;
- }
- data.copy(reader.inBuf, reader.writeCursor, 0);
- reader.writeCursor += data.length;
-
- callback(reader);
- };
-};
-
-TBufferedTransport.prototype = {
- commitPosition: function(){
- var unreadSize = this.writeCursor - this.readCursor;
- var bufSize = (unreadSize * 2 > this.defaultReadBufferSize) ?
- unreadSize * 2 : this.defaultReadBufferSize;
- var buf = new Buffer(bufSize);
- if (unreadSize > 0) {
- this.inBuf.copy(buf, 0, this.readCursor, this.writeCursor);
- }
- this.readCursor = 0;
- this.writeCursor = unreadSize;
- this.inBuf = buf;
- },
- rollbackPosition: function(){
- this.readCursor = 0;
- },
-
- // TODO: Implement open/close support
- isOpen: function() {return true;},
- open: function() {},
- close: function() {},
-
- ensureAvailable: function(len) {
- if (this.readCursor + len > this.writeCursor) {
- throw new InputBufferUnderrunError();
- }
- },
-
- read: function(len) {
- this.ensureAvailable(len);
- var buf = new Buffer(len);
- this.inBuf.copy(buf, 0, this.readCursor, this.readCursor + len);
- this.readCursor += len;
- return buf;
- },
-
- readByte: function() {
- this.ensureAvailable(1);
- return binary.readByte(this.inBuf[this.readCursor++]);
- },
-
- readI16: function() {
- this.ensureAvailable(2);
- var i16 = binary.readI16(this.inBuf, this.readCursor);
- this.readCursor += 2;
- return i16;
- },
-
- readI32: function() {
- this.ensureAvailable(4);
- var i32 = binary.readI32(this.inBuf, this.readCursor);
- this.readCursor += 4;
- return i32;
- },
-
- readDouble: function() {
- this.ensureAvailable(8);
- var d = binary.readDouble(this.inBuf, this.readCursor);
- this.readCursor += 8;
- return d;
- },
-
- readString: function(len) {
- this.ensureAvailable(len);
- var str = this.inBuf.toString('utf8', this.readCursor, this.readCursor + len);
- this.readCursor += len;
- return str;
- },
-
- borrow: function() {
- var obj = {buf: this.inBuf, readIndex: this.readCursor, writeIndex: this.writeCursor};
- return obj;
- },
-
- consume: function(bytesConsumed) {
- this.readCursor += bytesConsumed;
- },
-
- write: function(buf) {
- if (typeof(buf) === "string") {
- buf = new Buffer(buf, 'utf8');
- }
- this.outBuffers.push(buf);
- this.outCount += buf.length;
- },
-
- flush: function() {
- if (this.outCount < 1) {
- return;
- }
-
- var msg = new Buffer(this.outCount),
- pos = 0;
- this.outBuffers.forEach(function(buf) {
- buf.copy(msg, pos, 0);
- pos += buf.length;
- });
-
- if (this.onFlush) {
- this.onFlush(msg);
- }
-
- this.outBuffers = [];
- this.outCount = 0;
- }
-};
+module.exports.TBufferedTransport = require('./buffered_transport');
+module.exports.TFramedTransport = require('./framed_transport');
+module.exports.InputBufferUnderrunError = require('./input_buffer_underrun_error');