| -- | 
 | -- 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. | 
 | -- | 
 |  | 
 | require 'TProtocol' | 
 | require 'libluabpack' | 
 | require 'libluabitwise' | 
 |  | 
 | TBinaryProtocol = __TObject.new(TProtocolBase, { | 
 |   __type = 'TBinaryProtocol', | 
 |   VERSION_MASK = -65536, -- 0xffff0000 | 
 |   VERSION_1    = -2147418112, -- 0x80010000 | 
 |   TYPE_MASK    = 0x000000ff, | 
 |   strictRead   = false, | 
 |   strictWrite  = true | 
 | }) | 
 |  | 
 | function TBinaryProtocol:writeMessageBegin(name, ttype, seqid) | 
 |   if self.stirctWrite then | 
 |     self:writeI32(libluabitwise.bor(TBinaryProtocol.VERSION_1, ttype)) | 
 |     self:writeString(name) | 
 |     self:writeI32(seqid) | 
 |   else | 
 |     self:writeString(name) | 
 |     self:writeByte(ttype) | 
 |     self:writeI32(seqid) | 
 |   end | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeMessageEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeStructBegin(name) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeStructEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeFieldBegin(name, ttype, id) | 
 |   self:writeByte(ttype) | 
 |   self:writeI16(id) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeFieldEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeFieldStop() | 
 |   self:writeByte(TType.STOP); | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeMapBegin(ktype, vtype, size) | 
 |   self:writeByte(ktype) | 
 |   self:writeByte(vtype) | 
 |   self:writeI32(size) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeMapEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeListBegin(etype, size) | 
 |   self:writeByte(etype) | 
 |   self:writeI32(size) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeListEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeSetBegin(etype, size) | 
 |   self:writeByte(etype) | 
 |   self:writeI32(size) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeSetEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeBool(bool) | 
 |   if bool then | 
 |     self:writeByte(1) | 
 |   else | 
 |     self:writeByte(0) | 
 |   end | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeByte(byte) | 
 |   local buff = libluabpack.bpack('c', byte) | 
 |   self.trans:write(buff) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeI16(i16) | 
 |   local buff = libluabpack.bpack('s', i16) | 
 |   self.trans:write(buff) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeI32(i32) | 
 |   local buff = libluabpack.bpack('i', i32) | 
 |   self.trans:write(buff) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeI64(i64) | 
 |   local buff = libluabpack.bpack('l', i64) | 
 |   self.trans:write(buff) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeDouble(dub) | 
 |   local buff = libluabpack.bpack('d', dub) | 
 |   self.trans:write(buff) | 
 | end | 
 |  | 
 | function TBinaryProtocol:writeString(str) | 
 |   -- Should be utf-8 | 
 |   self:writeI32(string.len(str)) | 
 |   self.trans:write(str) | 
 | end | 
 |  | 
 | function TBinaryProtocol:readMessageBegin() | 
 |   local sz, ttype, name, seqid = self:readI32() | 
 |   if sz < 0 then | 
 |     local version = libluabitwise.band(sz, TBinaryProtocol.VERSION_MASK) | 
 |     if version ~= TBinaryProtocol.VERSION_1 then | 
 |       terror(TProtocolException:new{ | 
 |         message = 'Bad version in readMessageBegin: ' .. sz | 
 |       }) | 
 |     end | 
 |     ttype = libluabitwise.band(sz, TBinaryProtocol.TYPE_MASK) | 
 |     name = self:readString() | 
 |     seqid = self:readI32() | 
 |   else | 
 |     if self.strictRead then | 
 |       terror(TProtocolException:new{message = 'No protocol version header'}) | 
 |     end | 
 |     name = self.trans:readAll(sz) | 
 |     ttype = self:readByte() | 
 |     seqid = self:readI32() | 
 |   end | 
 |   return name, ttype, seqid | 
 | end | 
 |  | 
 | function TBinaryProtocol:readMessageEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:readStructBegin() | 
 |   return nil | 
 | end | 
 |  | 
 | function TBinaryProtocol:readStructEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:readFieldBegin() | 
 |   local ttype = self:readByte() | 
 |   if ttype == TType.STOP then | 
 |     return nil, ttype, 0 | 
 |   end | 
 |   local id = self:readI16() | 
 |   return nil, ttype, id | 
 | end | 
 |  | 
 | function TBinaryProtocol:readFieldEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:readMapBegin() | 
 |   local ktype = self:readByte() | 
 |   local vtype = self:readByte() | 
 |   local size = self:readI32() | 
 |   return ktype, vtype, size | 
 | end | 
 |  | 
 | function TBinaryProtocol:readMapEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:readListBegin() | 
 |   local etype = self:readByte() | 
 |   local size = self:readI32() | 
 |   return etype, size | 
 | end | 
 |  | 
 | function TBinaryProtocol:readListEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:readSetBegin() | 
 |   local etype = self:readByte() | 
 |   local size = self:readI32() | 
 |   return etype, size | 
 | end | 
 |  | 
 | function TBinaryProtocol:readSetEnd() | 
 | end | 
 |  | 
 | function TBinaryProtocol:readBool() | 
 |   local byte = self:readByte() | 
 |   if byte == 0 then | 
 |     return false | 
 |   end | 
 |   return true | 
 | end | 
 |  | 
 | function TBinaryProtocol:readByte() | 
 |   local buff = self.trans:readAll(1) | 
 |   local val = libluabpack.bunpack('c', buff) | 
 |   return val | 
 | end | 
 |  | 
 | function TBinaryProtocol:readI16() | 
 |   local buff = self.trans:readAll(2) | 
 |   local val = libluabpack.bunpack('s', buff) | 
 |   return val | 
 | end | 
 |  | 
 | function TBinaryProtocol:readI32() | 
 |   local buff = self.trans:readAll(4) | 
 |   local val = libluabpack.bunpack('i', buff) | 
 |   return val | 
 | end | 
 |  | 
 | function TBinaryProtocol:readI64() | 
 |   local buff = self.trans:readAll(8) | 
 |   local val = libluabpack.bunpack('l', buff) | 
 |   return val | 
 | end | 
 |  | 
 | function TBinaryProtocol:readDouble() | 
 |   local buff = self.trans:readAll(8) | 
 |   local val = libluabpack.bunpack('d', buff) | 
 |   return val | 
 | end | 
 |  | 
 | function TBinaryProtocol:readString() | 
 |   local len = self:readI32() | 
 |   local str = self.trans:readAll(len) | 
 |   return str | 
 | end | 
 |  | 
 | TBinaryProtocolFactory = TProtocolFactory:new{ | 
 |   __type = 'TBinaryProtocolFactory', | 
 |   strictRead = false | 
 | } | 
 |  | 
 | function TBinaryProtocolFactory:getProtocol(trans) | 
 |   -- TODO Enforce that this must be a transport class (ie not a bool) | 
 |   if not trans then | 
 |     terror(TProtocolException:new{ | 
 |       message = 'Must supply a transport to ' .. ttype(self) | 
 |     }) | 
 |   end | 
 |   return TBinaryProtocol:new{ | 
 |     trans = trans, | 
 |     strictRead = self.strictRead, | 
 |     strictWrite = true | 
 |   } | 
 | end |