1-- 2-- Licensed to the Apache Software Foundation (ASF) under one 3-- or more contributor license agreements. See the NOTICE file 4-- distributed with this work for additional information 5-- regarding copyright ownership. The ASF licenses this file 6-- to you under the Apache License, Version 2.0 (the 7-- "License"); you may not use this file except in compliance 8-- with the License. You may obtain a copy of the License at 9-- 10-- http://www.apache.org/licenses/LICENSE-2.0 11-- 12-- Unless required by applicable law or agreed to in writing, 13-- software distributed under the License is distributed on an 14-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15-- KIND, either express or implied. See the License for the 16-- specific language governing permissions and limitations 17-- under the License. 18-- 19 20require 'TProtocol' 21require 'libluabpack' 22require 'libluabitwise' 23 24TBinaryProtocol = __TObject.new(TProtocolBase, { 25 __type = 'TBinaryProtocol', 26 VERSION_MASK = -65536, -- 0xffff0000 27 VERSION_1 = -2147418112, -- 0x80010000 28 TYPE_MASK = 0x000000ff, 29 strictRead = false, 30 strictWrite = true 31}) 32 33function TBinaryProtocol:writeMessageBegin(name, ttype, seqid) 34 if self.strictWrite then 35 self:writeI32(libluabitwise.bor(TBinaryProtocol.VERSION_1, ttype)) 36 self:writeString(name) 37 self:writeI32(seqid) 38 else 39 self:writeString(name) 40 self:writeByte(ttype) 41 self:writeI32(seqid) 42 end 43end 44 45function TBinaryProtocol:writeMessageEnd() 46end 47 48function TBinaryProtocol:writeStructBegin(name) 49end 50 51function TBinaryProtocol:writeStructEnd() 52end 53 54function TBinaryProtocol:writeFieldBegin(name, ttype, id) 55 self:writeByte(ttype) 56 self:writeI16(id) 57end 58 59function TBinaryProtocol:writeFieldEnd() 60end 61 62function TBinaryProtocol:writeFieldStop() 63 self:writeByte(TType.STOP); 64end 65 66function TBinaryProtocol:writeMapBegin(ktype, vtype, size) 67 self:writeByte(ktype) 68 self:writeByte(vtype) 69 self:writeI32(size) 70end 71 72function TBinaryProtocol:writeMapEnd() 73end 74 75function TBinaryProtocol:writeListBegin(etype, size) 76 self:writeByte(etype) 77 self:writeI32(size) 78end 79 80function TBinaryProtocol:writeListEnd() 81end 82 83function TBinaryProtocol:writeSetBegin(etype, size) 84 self:writeByte(etype) 85 self:writeI32(size) 86end 87 88function TBinaryProtocol:writeSetEnd() 89end 90 91function TBinaryProtocol:writeBool(bool) 92 if bool then 93 self:writeByte(1) 94 else 95 self:writeByte(0) 96 end 97end 98 99function TBinaryProtocol:writeByte(byte) 100 local buff = libluabpack.bpack('c', byte) 101 self.trans:write(buff) 102end 103 104function TBinaryProtocol:writeI16(i16) 105 local buff = libluabpack.bpack('s', i16) 106 self.trans:write(buff) 107end 108 109function TBinaryProtocol:writeI32(i32) 110 local buff = libluabpack.bpack('i', i32) 111 self.trans:write(buff) 112end 113 114function TBinaryProtocol:writeI64(i64) 115 local buff = libluabpack.bpack('l', i64) 116 self.trans:write(buff) 117end 118 119function TBinaryProtocol:writeDouble(dub) 120 local buff = libluabpack.bpack('d', dub) 121 self.trans:write(buff) 122end 123 124function TBinaryProtocol:writeString(str) 125 -- Should be utf-8 126 self:writeI32(string.len(str)) 127 self.trans:write(str) 128end 129 130function TBinaryProtocol:readMessageBegin() 131 local sz, ttype, name, seqid = self:readI32() 132 if sz < 0 then 133 local version = libluabitwise.band(sz, TBinaryProtocol.VERSION_MASK) 134 if version ~= TBinaryProtocol.VERSION_1 then 135 terror(TProtocolException:new{ 136 message = 'Bad version in readMessageBegin: ' .. sz 137 }) 138 end 139 ttype = libluabitwise.band(sz, TBinaryProtocol.TYPE_MASK) 140 name = self:readString() 141 seqid = self:readI32() 142 else 143 if self.strictRead then 144 terror(TProtocolException:new{message = 'No protocol version header'}) 145 end 146 name = self.trans:readAll(sz) 147 ttype = self:readByte() 148 seqid = self:readI32() 149 end 150 return name, ttype, seqid 151end 152 153function TBinaryProtocol:readMessageEnd() 154end 155 156function TBinaryProtocol:readStructBegin() 157 return nil 158end 159 160function TBinaryProtocol:readStructEnd() 161end 162 163function TBinaryProtocol:readFieldBegin() 164 local ttype = self:readByte() 165 if ttype == TType.STOP then 166 return nil, ttype, 0 167 end 168 local id = self:readI16() 169 return nil, ttype, id 170end 171 172function TBinaryProtocol:readFieldEnd() 173end 174 175function TBinaryProtocol:readMapBegin() 176 local ktype = self:readByte() 177 local vtype = self:readByte() 178 local size = self:readI32() 179 return ktype, vtype, size 180end 181 182function TBinaryProtocol:readMapEnd() 183end 184 185function TBinaryProtocol:readListBegin() 186 local etype = self:readByte() 187 local size = self:readI32() 188 return etype, size 189end 190 191function TBinaryProtocol:readListEnd() 192end 193 194function TBinaryProtocol:readSetBegin() 195 local etype = self:readByte() 196 local size = self:readI32() 197 return etype, size 198end 199 200function TBinaryProtocol:readSetEnd() 201end 202 203function TBinaryProtocol:readBool() 204 local byte = self:readByte() 205 if byte == 0 then 206 return false 207 end 208 return true 209end 210 211function TBinaryProtocol:readByte() 212 local buff = self.trans:readAll(1) 213 local val = libluabpack.bunpack('c', buff) 214 return val 215end 216 217function TBinaryProtocol:readI16() 218 local buff = self.trans:readAll(2) 219 local val = libluabpack.bunpack('s', buff) 220 return val 221end 222 223function TBinaryProtocol:readI32() 224 local buff = self.trans:readAll(4) 225 local val = libluabpack.bunpack('i', buff) 226 return val 227end 228 229function TBinaryProtocol:readI64() 230 local buff = self.trans:readAll(8) 231 local val = libluabpack.bunpack('l', buff) 232 return val 233end 234 235function TBinaryProtocol:readDouble() 236 local buff = self.trans:readAll(8) 237 local val = libluabpack.bunpack('d', buff) 238 return val 239end 240 241function TBinaryProtocol:readString() 242 local len = self:readI32() 243 local str = self.trans:readAll(len) 244 return str 245end 246 247TBinaryProtocolFactory = TProtocolFactory:new{ 248 __type = 'TBinaryProtocolFactory', 249 strictRead = false 250} 251 252function TBinaryProtocolFactory:getProtocol(trans) 253 -- TODO Enforce that this must be a transport class (ie not a bool) 254 if not trans then 255 terror(TProtocolException:new{ 256 message = 'Must supply a transport to ' .. ttype(self) 257 }) 258 end 259 return TBinaryProtocol:new{ 260 trans = trans, 261 strictRead = self.strictRead, 262 strictWrite = true 263 } 264end 265