-- -- 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.strictWrite 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