]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/lua/TCompactProtocol.lua
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / lua / TCompactProtocol.lua
CommitLineData
f67539c2
TL
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'
23require 'liblualongnumber'
24
25TCompactProtocol = __TObject.new(TProtocolBase, {
26 __type = 'TCompactProtocol',
27 COMPACT_PROTOCOL_ID = 0x82,
28 COMPACT_VERSION = 1,
29 COMPACT_VERSION_MASK = 0x1f,
30 COMPACT_TYPE_MASK = 0xE0,
31 COMPACT_TYPE_BITS = 0x07,
32 COMPACT_TYPE_SHIFT_AMOUNT = 5,
33
34 -- Used to keep track of the last field for the current and previous structs,
35 -- so we can do the delta stuff.
36 lastField = {},
37 lastFieldId = 0,
38 lastFieldIndex = 1,
39
40 -- If we encounter a boolean field begin, save the TField here so it can
41 -- have the value incorporated.
42 booleanFieldName = "",
43 booleanFieldId = 0,
44 booleanFieldPending = false,
45
46 -- If we read a field header, and it's a boolean field, save the boolean
47 -- value here so that readBool can use it.
48 boolValue = false,
49 boolValueIsNotNull = false,
50})
51
52TCompactType = {
53 COMPACT_BOOLEAN_TRUE = 0x01,
54 COMPACT_BOOLEAN_FALSE = 0x02,
55 COMPACT_BYTE = 0x03,
56 COMPACT_I16 = 0x04,
57 COMPACT_I32 = 0x05,
58 COMPACT_I64 = 0x06,
59 COMPACT_DOUBLE = 0x07,
60 COMPACT_BINARY = 0x08,
61 COMPACT_LIST = 0x09,
62 COMPACT_SET = 0x0A,
63 COMPACT_MAP = 0x0B,
64 COMPACT_STRUCT = 0x0C
65}
66
67TTypeToCompactType = {}
68TTypeToCompactType[TType.STOP] = TType.STOP
69TTypeToCompactType[TType.BOOL] = TCompactType.COMPACT_BOOLEAN_TRUE
70TTypeToCompactType[TType.BYTE] = TCompactType.COMPACT_BYTE
71TTypeToCompactType[TType.I16] = TCompactType.COMPACT_I16
72TTypeToCompactType[TType.I32] = TCompactType.COMPACT_I32
73TTypeToCompactType[TType.I64] = TCompactType.COMPACT_I64
74TTypeToCompactType[TType.DOUBLE] = TCompactType.COMPACT_DOUBLE
75TTypeToCompactType[TType.STRING] = TCompactType.COMPACT_BINARY
76TTypeToCompactType[TType.LIST] = TCompactType.COMPACT_LIST
77TTypeToCompactType[TType.SET] = TCompactType.COMPACT_SET
78TTypeToCompactType[TType.MAP] = TCompactType.COMPACT_MAP
79TTypeToCompactType[TType.STRUCT] = TCompactType.COMPACT_STRUCT
80
81CompactTypeToTType = {}
82CompactTypeToTType[TType.STOP] = TType.STOP
83CompactTypeToTType[TCompactType.COMPACT_BOOLEAN_TRUE] = TType.BOOL
84CompactTypeToTType[TCompactType.COMPACT_BOOLEAN_FALSE] = TType.BOOL
85CompactTypeToTType[TCompactType.COMPACT_BYTE] = TType.BYTE
86CompactTypeToTType[TCompactType.COMPACT_I16] = TType.I16
87CompactTypeToTType[TCompactType.COMPACT_I32] = TType.I32
88CompactTypeToTType[TCompactType.COMPACT_I64] = TType.I64
89CompactTypeToTType[TCompactType.COMPACT_DOUBLE] = TType.DOUBLE
90CompactTypeToTType[TCompactType.COMPACT_BINARY] = TType.STRING
91CompactTypeToTType[TCompactType.COMPACT_LIST] = TType.LIST
92CompactTypeToTType[TCompactType.COMPACT_SET] = TType.SET
93CompactTypeToTType[TCompactType.COMPACT_MAP] = TType.MAP
94CompactTypeToTType[TCompactType.COMPACT_STRUCT] = TType.STRUCT
95
96function TCompactProtocol:resetLastField()
97 self.lastField = {}
98 self.lastFieldId = 0
99 self.lastFieldIndex = 1
100end
101
102function TCompactProtocol:packCompactType(ktype, vtype)
103 return libluabitwise.bor(libluabitwise.shiftl(ktype, 4), vtype)
104end
105
106function TCompactProtocol:writeMessageBegin(name, ttype, seqid)
107 self:writeByte(TCompactProtocol.COMPACT_PROTOCOL_ID)
108 self:writeByte(libluabpack.packMesgType(TCompactProtocol.COMPACT_VERSION,
109 TCompactProtocol.COMPACT_VERSION_MASK,ttype,
110 TCompactProtocol.COMPACT_TYPE_SHIFT_AMOUNT,
111 TCompactProtocol.COMPACT_TYPE_MASK))
112 self:writeVarint32(seqid)
113 self:writeString(name)
114 self:resetLastField()
115end
116
117function TCompactProtocol:writeMessageEnd()
118end
119
120function TCompactProtocol:writeStructBegin(name)
121 self.lastFieldIndex = self.lastFieldIndex + 1
122 self.lastField[self.lastFieldIndex] = self.lastFieldId
123 self.lastFieldId = 0
124end
125
126function TCompactProtocol:writeStructEnd()
127 self.lastFieldIndex = self.lastFieldIndex - 1
128 self.lastFieldId = self.lastField[self.lastFieldIndex]
129end
130
131function TCompactProtocol:writeFieldBegin(name, ttype, id)
132 if ttype == TType.BOOL then
133 self.booleanFieldName = name
134 self.booleanFieldId = id
135 self.booleanFieldPending = true
136 else
137 self:writeFieldBeginInternal(name, ttype, id, -1)
138 end
139end
140
141function TCompactProtocol:writeFieldEnd()
142end
143
144function TCompactProtocol:writeFieldStop()
145 self:writeByte(TType.STOP);
146end
147
148function TCompactProtocol:writeMapBegin(ktype, vtype, size)
149 if size == 0 then
150 self:writeByte(0)
151 else
152 self:writeVarint32(size)
153 self:writeByte(self:packCompactType(TTypeToCompactType[ktype], TTypeToCompactType[vtype]))
154 end
155end
156
157function TCompactProtocol:writeMapEnd()
158end
159
160function TCompactProtocol:writeListBegin(etype, size)
161 self:writeCollectionBegin(etype, size)
162end
163
164function TCompactProtocol:writeListEnd()
165end
166
167function TCompactProtocol:writeSetBegin(etype, size)
168 self:writeCollectionBegin(etype, size)
169end
170
171function TCompactProtocol:writeSetEnd()
172end
173
174function TCompactProtocol:writeBool(bool)
175 local value = TCompactType.COMPACT_BOOLEAN_FALSE
176 if bool then
177 value = TCompactType.COMPACT_BOOLEAN_TRUE
178 end
179 print(value,self.booleanFieldPending,self.booleanFieldId)
180 if self.booleanFieldPending then
181 self:writeFieldBeginInternal(self.booleanFieldName, TType.BOOL, self.booleanFieldId, value)
182 self.booleanFieldPending = false
183 else
184 self:writeByte(value)
185 end
186end
187
188function TCompactProtocol:writeByte(byte)
189 local buff = libluabpack.bpack('c', byte)
190 self.trans:write(buff)
191end
192
193function TCompactProtocol:writeI16(i16)
194 self:writeVarint32(libluabpack.i32ToZigzag(i16))
195end
196
197function TCompactProtocol:writeI32(i32)
198 self:writeVarint32(libluabpack.i32ToZigzag(i32))
199end
200
201function TCompactProtocol:writeI64(i64)
202 self:writeVarint64(libluabpack.i64ToZigzag(i64))
203end
204
205function TCompactProtocol:writeDouble(dub)
206 local buff = libluabpack.bpack('d', dub)
207 self.trans:write(buff)
208end
209
210function TCompactProtocol:writeString(str)
211 -- Should be utf-8
212 self:writeBinary(str)
213end
214
215function TCompactProtocol:writeBinary(str)
216 -- Should be utf-8
217 self:writeVarint32(string.len(str))
218 self.trans:write(str)
219end
220
221function TCompactProtocol:writeFieldBeginInternal(name, ttype, id, typeOverride)
222 if typeOverride == -1 then
223 typeOverride = TTypeToCompactType[ttype]
224 end
225 local offset = id - self.lastFieldId
226 if id > self.lastFieldId and offset <= 15 then
227 self:writeByte(libluabitwise.bor(libluabitwise.shiftl(offset, 4), typeOverride))
228 else
229 self:writeByte(typeOverride)
230 self:writeI16(id)
231 end
232 self.lastFieldId = id
233end
234
235function TCompactProtocol:writeCollectionBegin(etype, size)
236 if size <= 14 then
237 self:writeByte(libluabitwise.bor(libluabitwise.shiftl(size, 4), TTypeToCompactType[etype]))
238 else
239 self:writeByte(libluabitwise.bor(0xf0, TTypeToCompactType[etype]))
240 self:writeVarint32(size)
241 end
242end
243
244function TCompactProtocol:writeVarint32(i32)
245 -- Should be utf-8
246 local str = libluabpack.toVarint32(i32)
247 self.trans:write(str)
248end
249
250function TCompactProtocol:writeVarint64(i64)
251 -- Should be utf-8
252 local str = libluabpack.toVarint64(i64)
253 self.trans:write(str)
254end
255
256function TCompactProtocol:readMessageBegin()
257 local protocolId = self:readSignByte()
258 if protocolId ~= self.COMPACT_PROTOCOL_ID then
259 terror(TProtocolException:new{
260 message = "Expected protocol id " .. self.COMPACT_PROTOCOL_ID .. " but got " .. protocolId})
261 end
262 local versionAndType = self:readSignByte()
263 local version = libluabitwise.band(versionAndType, self.COMPACT_VERSION_MASK)
264 local ttype = libluabitwise.band(libluabitwise.shiftr(versionAndType,
265 self.COMPACT_TYPE_SHIFT_AMOUNT), self.COMPACT_TYPE_BITS)
266 if version ~= self.COMPACT_VERSION then
267 terror(TProtocolException:new{
268 message = "Expected version " .. self.COMPACT_VERSION .. " but got " .. version})
269 end
270 local seqid = self:readVarint32()
271 local name = self:readString()
272 return name, ttype, seqid
273end
274
275function TCompactProtocol:readMessageEnd()
276end
277
278function TCompactProtocol:readStructBegin()
279 self.lastField[self.lastFieldIndex] = self.lastFieldId
280 self.lastFieldIndex = self.lastFieldIndex + 1
281 self.lastFieldId = 0
282 return nil
283end
284
285function TCompactProtocol:readStructEnd()
286 self.lastFieldIndex = self.lastFieldIndex - 1
287 self.lastFieldId = self.lastField[self.lastFieldIndex]
288end
289
290function TCompactProtocol:readFieldBegin()
291 local field_and_ttype = self:readSignByte()
292 local ttype = self:getTType(field_and_ttype)
293 if ttype == TType.STOP then
294 return nil, ttype, 0
295 end
296 -- mask off the 4 MSB of the type header. it could contain a field id delta.
297 local modifier = libluabitwise.shiftr(libluabitwise.band(field_and_ttype, 0xf0), 4)
298 local id = 0
299 if modifier == 0 then
300 id = self:readI16()
301 else
302 id = self.lastFieldId + modifier
303 end
304 if ttype == TType.BOOL then
305 boolValue = libluabitwise.band(field_and_ttype, 0x0f) == TCompactType.COMPACT_BOOLEAN_TRUE
306 boolValueIsNotNull = true
307 end
308 self.lastFieldId = id
309 return nil, ttype, id
310end
311
312function TCompactProtocol:readFieldEnd()
313end
314
315function TCompactProtocol:readMapBegin()
316 local size = self:readVarint32()
317 if size < 0 then
318 return nil,nil,nil
319 end
320 local kvtype = self:readSignByte()
321 local ktype = self:getTType(libluabitwise.shiftr(kvtype, 4))
322 local vtype = self:getTType(kvtype)
323 return ktype, vtype, size
324end
325
326function TCompactProtocol:readMapEnd()
327end
328
329function TCompactProtocol:readListBegin()
330 local size_and_type = self:readSignByte()
331 local size = libluabitwise.band(libluabitwise.shiftr(size_and_type, 4), 0x0f)
332 if size == 15 then
333 size = self:readVarint32()
334 end
335 if size < 0 then
336 return nil,nil
337 end
338 local etype = self:getTType(libluabitwise.band(size_and_type, 0x0f))
339 return etype, size
340end
341
342function TCompactProtocol:readListEnd()
343end
344
345function TCompactProtocol:readSetBegin()
346 return self:readListBegin()
347end
348
349function TCompactProtocol:readSetEnd()
350end
351
352function TCompactProtocol:readBool()
353 if boolValueIsNotNull then
354 boolValueIsNotNull = true
355 return boolValue
356 end
357 local val = self:readSignByte()
358 if val == TCompactType.COMPACT_BOOLEAN_TRUE then
359 return true
360 end
361 return false
362end
363
364function TCompactProtocol:readByte()
365 local buff = self.trans:readAll(1)
366 local val = libluabpack.bunpack('c', buff)
367 return val
368end
369
370function TCompactProtocol:readSignByte()
371 local buff = self.trans:readAll(1)
372 local val = libluabpack.bunpack('C', buff)
373 return val
374end
375
376function TCompactProtocol:readI16()
377 return self:readI32()
378end
379
380function TCompactProtocol:readI32()
381 local v = self:readVarint32()
382 local value = libluabpack.zigzagToI32(v)
383 return value
384end
385
386function TCompactProtocol:readI64()
387 local value = self:readVarint64()
388 return value
389end
390
391function TCompactProtocol:readDouble()
392 local buff = self.trans:readAll(8)
393 local val = libluabpack.bunpack('d', buff)
394 return val
395end
396
397function TCompactProtocol:readString()
398 return self:readBinary()
399end
400
401function TCompactProtocol:readBinary()
402 local size = self:readVarint32()
403 if size <= 0 then
404 return ""
405 end
406 return self.trans:readAll(size)
407end
408
409function TCompactProtocol:readVarint32()
410 local shiftl = 0
411 local result = 0
412 while true do
413 b = self:readByte()
414 result = libluabitwise.bor(result,
415 libluabitwise.shiftl(libluabitwise.band(b, 0x7f), shiftl))
416 if libluabitwise.band(b, 0x80) ~= 0x80 then
417 break
418 end
419 shiftl = shiftl + 7
420 end
421 return result
422end
423
424function TCompactProtocol:readVarint64()
425 local result = liblualongnumber.new
426 local data = result(0)
427 local shiftl = 0
428 while true do
429 b = self:readByte()
430 endFlag, data = libluabpack.fromVarint64(b, shiftl, data)
431 shiftl = shiftl + 7
432 if endFlag == 0 then
433 break
434 end
435 end
436 return data
437end
438
439function TCompactProtocol:getTType(ctype)
440 return CompactTypeToTType[libluabitwise.band(ctype, 0x0f)]
441end
442
443TCompactProtocolFactory = TProtocolFactory:new{
444 __type = 'TCompactProtocolFactory',
445}
446
447function TCompactProtocolFactory:getProtocol(trans)
448 -- TODO Enforce that this must be a transport class (ie not a bool)
449 if not trans then
450 terror(TProtocolException:new{
451 message = 'Must supply a transport to ' .. ttype(self)
452 })
453 end
454 return TCompactProtocol:new{
455 trans = trans
456 }
457end