blob: 1b6c3453562b92ac2a57e3898ac6574a62491179 [file] [log] [blame]
/*
* 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 util = require('util'),
Thrift = require('./thrift'),
Type = Thrift.Type;
var BinaryParser = require('./binary_parser').BinaryParser;
BinaryParser.bigEndian = true;
var UNKNOWN = 0,
INVALID_DATA = 1,
NEGATIVE_SIZE = 2,
SIZE_LIMIT = 3,
BAD_VERSION = 4;
var TProtocolException = function(type, message) {
Error.call(this, message);
this.name = 'TProtocolException';
this.type = type;
}
util.inherits(TProtocolException, Error);
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();
}
// NastyHaxx. JavaScript forces hex constants to be
// positive, converting this into a long. If we hardcode the int value
// instead it'll stay in 32 bit-land.
var VERSION_MASK = -65536, // 0xffff0000
VERSION_1 = -2147418112, // 0x80010000
TYPE_MASK = 0x000000ff;
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) {
console.log('write set', 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(byte) {
this.trans.write(BinaryParser.fromByte(byte));
}
TBinaryProtocol.prototype.writeI16 = function(i16) {
this.trans.write(BinaryParser.fromShort(i16));
}
TBinaryProtocol.prototype.writeI32 = function(i32) {
this.trans.write(BinaryParser.fromInt(i32));
}
TBinaryProtocol.prototype.writeI64 = function(i64) {
this.trans.write(BinaryParser.fromLong(i64));
}
TBinaryProtocol.prototype.writeDouble = function(dub) {
this.trans.write(BinaryParser.fromDouble(dub));
}
TBinaryProtocol.prototype.writeString = function(str) {
this.writeI32(str.length);
this.trans.write(str);
}
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 TProtocolException(BAD_VERSION, "Bad version in readMessageBegin: " + sz);
}
type = sz & TYPE_MASK;
name = this.readString();
seqid = this.readI32();
} else {
if (this.strictRead) {
throw TProtocolException(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 byte = this.readByte();
if (byte == 0) {
return false;
}
return true;
}
TBinaryProtocol.prototype.readByte = function() {
var buff = this.trans.read(1);
return BinaryParser.toByte(buff);
}
TBinaryProtocol.prototype.readI16 = function() {
var buff = this.trans.read(2);
return BinaryParser.toShort(buff);
}
TBinaryProtocol.prototype.readI32 = function() {
var buff = this.trans.read(4);
// console.log("read buf: ");
// console.log(buff);
// console.log("result: " + BinaryParser.toInt(buff));
return BinaryParser.toInt(buff);
}
TBinaryProtocol.prototype.readI64 = function() {
var buff = this.trans.read(8);
return BinaryParser.toLong(buff);
}
TBinaryProtocol.prototype.readDouble = function() {
var buff = this.trans.read(8);
return BinaryParser.toFloat(buff);
}
TBinaryProtocol.prototype.readBinary = function() {
var len = this.readI32();
return this.trans.read(len);
}
TBinaryProtocol.prototype.readString = function() {
var r = this.readBinary().toString('binary');
// console.log("readString: " + r);
return r;
}
TBinaryProtocol.prototype.getTransport = function() {
return this.trans;
}
TBinaryProtocol.prototype.skip = function(type) {
// console.log("skip: " + 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 r = this.readMapBegin();
for (var i = 0; i < r.size; ++i) {
this.skip(r.ktype);
this.skip(r.vtype);
}
this.readMapEnd();
break;
case Type.SET:
var r = this.readSetBegin();
for (var i = 0; i < r.size; ++i) {
this.skip(r.etype);
}
this.readSetEnd();
break;
case Type.LIST:
var r = this.readListBegin();
for (var i = 0; i < r.size; ++i) {
this.skip(r.etype);
}
this.readListEnd();
break;
default:
throw Error("Invalid type: " + type);
}
}