mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
* add jaeger support, link hot container & req span * adds jaeger support now with FN_JAEGER_URL, there's a simple tutorial in the operating/metrics.md file now and it's pretty easy to get up and running. * links a hot request span to a hot container span. when we change this to sample at a lower ratio we'll need to finagle the hot container span to always sample or something, otherwise we'll hide that info. at least, since we're sampling at 100% for now if this is flipped on, can see freeze/unfreeze etc. if they hit. this is useful for debugging. note that zipkin's exporter does not follow the link at all, hence jaeger... and they're backed by the Cloud Empire now (CNCF) so we'll probably use it anyway. * vendor: add thrift for jaeger
728 lines
18 KiB
Lua
728 lines
18 KiB
Lua
--
|
|
-- 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'
|
|
|
|
TJSONProtocol = __TObject.new(TProtocolBase, {
|
|
__type = 'TJSONProtocol',
|
|
THRIFT_JSON_PROTOCOL_VERSION = 1,
|
|
jsonContext = {},
|
|
jsonContextVal = {first = true, colon = true, ttype = 2, null = true},
|
|
jsonContextIndex = 1,
|
|
hasReadByte = ""
|
|
})
|
|
|
|
TTypeToString = {}
|
|
TTypeToString[TType.BOOL] = "tf"
|
|
TTypeToString[TType.BYTE] = "i8"
|
|
TTypeToString[TType.I16] = "i16"
|
|
TTypeToString[TType.I32] = "i32"
|
|
TTypeToString[TType.I64] = "i64"
|
|
TTypeToString[TType.DOUBLE] = "dbl"
|
|
TTypeToString[TType.STRING] = "str"
|
|
TTypeToString[TType.STRUCT] = "rec"
|
|
TTypeToString[TType.LIST] = "lst"
|
|
TTypeToString[TType.SET] = "set"
|
|
TTypeToString[TType.MAP] = "map"
|
|
|
|
StringToTType = {
|
|
tf = TType.BOOL,
|
|
i8 = TType.BYTE,
|
|
i16 = TType.I16,
|
|
i32 = TType.I32,
|
|
i64 = TType.I64,
|
|
dbl = TType.DOUBLE,
|
|
str = TType.STRING,
|
|
rec = TType.STRUCT,
|
|
map = TType.MAP,
|
|
set = TType.SET,
|
|
lst = TType.LIST
|
|
}
|
|
|
|
JSONNode = {
|
|
ObjectBegin = '{',
|
|
ObjectEnd = '}',
|
|
ArrayBegin = '[',
|
|
ArrayEnd = ']',
|
|
PairSeparator = ':',
|
|
ElemSeparator = ',',
|
|
Backslash = '\\',
|
|
StringDelimiter = '"',
|
|
ZeroChar = '0',
|
|
EscapeChar = 'u',
|
|
Nan = 'NaN',
|
|
Infinity = 'Infinity',
|
|
NegativeInfinity = '-Infinity',
|
|
EscapeChars = "\"\\bfnrt",
|
|
EscapePrefix = "\\u00"
|
|
}
|
|
|
|
EscapeCharVals = {
|
|
'"', '\\', '\b', '\f', '\n', '\r', '\t'
|
|
}
|
|
|
|
JSONCharTable = {
|
|
--0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
0, 0, 0, 0, 0, 0, 0, 0, 98,116,110, 0,102,114, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 1,34, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
}
|
|
|
|
-- character table string
|
|
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
|
|
-- encoding
|
|
function base64_encode(data)
|
|
return ((data:gsub('.', function(x)
|
|
local r,b='',x:byte()
|
|
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
|
|
return r;
|
|
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
|
|
if (#x < 6) then return '' end
|
|
local c=0
|
|
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
|
|
return b:sub(c+1,c+1)
|
|
end)..({ '', '==', '=' })[#data%3+1])
|
|
end
|
|
|
|
-- decoding
|
|
function base64_decode(data)
|
|
data = string.gsub(data, '[^'..b..'=]', '')
|
|
return (data:gsub('.', function(x)
|
|
if (x == '=') then return '' end
|
|
local r,f='',(b:find(x)-1)
|
|
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
|
|
return r;
|
|
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
|
|
if (#x ~= 8) then return '' end
|
|
local c=0
|
|
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
|
|
return string.char(c)
|
|
end))
|
|
end
|
|
|
|
function TJSONProtocol:resetContext()
|
|
self.jsonContext = {}
|
|
self.jsonContextVal = {first = true, colon = true, ttype = 2, null = true}
|
|
self.jsonContextIndex = 1
|
|
end
|
|
|
|
function TJSONProtocol:contextPush(context)
|
|
self.jsonContextIndex = self.jsonContextIndex + 1
|
|
self.jsonContext[self.jsonContextIndex] = self.jsonContextVal
|
|
self.jsonContextVal = context
|
|
end
|
|
|
|
function TJSONProtocol:contextPop()
|
|
self.jsonContextVal = self.jsonContext[self.jsonContextIndex]
|
|
self.jsonContextIndex = self.jsonContextIndex - 1
|
|
end
|
|
|
|
function TJSONProtocol:escapeNum()
|
|
if self.jsonContextVal.ttype == 1 then
|
|
return self.jsonContextVal.colon
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:writeElemSeparator()
|
|
if self.jsonContextVal.null then
|
|
return
|
|
end
|
|
if self.jsonContextVal.first then
|
|
self.jsonContextVal.first = false
|
|
else
|
|
if self.jsonContextVal.ttype == 1 then
|
|
if self.jsonContextVal.colon then
|
|
self.trans:write(JSONNode.PairSeparator)
|
|
self.jsonContextVal.colon = false
|
|
else
|
|
self.trans:write(JSONNode.ElemSeparator)
|
|
self.jsonContextVal.colon = true
|
|
end
|
|
else
|
|
self.trans:write(JSONNode.ElemSeparator)
|
|
end
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:hexChar(val)
|
|
val = libluabitwise.band(val, 0x0f)
|
|
if val < 10 then
|
|
return val + 48
|
|
else
|
|
return val + 87
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONEscapeChar(ch)
|
|
self.trans:write(JSONNode.EscapePrefix)
|
|
local outCh = hexChar(libluabitwise.shiftr(ch, 4))
|
|
local buff = libluabpack.bpack('c', outCh)
|
|
self.trans:write(buff)
|
|
outCh = hexChar(ch)
|
|
buff = libluabpack.bpack('c', outCh)
|
|
self.trans:write(buff)
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONChar(byte)
|
|
ch = string.byte(byte)
|
|
if ch >= 0x30 then
|
|
if ch == JSONNode.Backslash then
|
|
self.trans:write(JSONNode.Backslash)
|
|
self.trans:write(JSONNode.Backslash)
|
|
else
|
|
self.trans:write(byte)
|
|
end
|
|
else
|
|
local outCh = JSONCharTable[ch+1]
|
|
if outCh == 1 then
|
|
self.trans:write(byte)
|
|
elseif outCh > 1 then
|
|
self.trans:write(JSONNode.Backslash)
|
|
local buff = libluabpack.bpack('c', outCh)
|
|
self.trans:write(buff)
|
|
else
|
|
self:writeJSONEscapeChar(ch)
|
|
end
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONString(str)
|
|
self:writeElemSeparator()
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
-- TODO escape special characters
|
|
local length = string.len(str)
|
|
local ii = 1
|
|
while ii <= length do
|
|
self:writeJSONChar(string.sub(str, ii, ii))
|
|
ii = ii + 1
|
|
end
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONBase64(str)
|
|
self:writeElemSeparator()
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
local length = string.len(str)
|
|
local offset = 1
|
|
while length >= 3 do
|
|
-- Encode 3 bytes at a time
|
|
local bytes = base64_encode(string.sub(str, offset, offset+3))
|
|
self.trans:write(bytes)
|
|
length = length - 3
|
|
offset = offset + 3
|
|
end
|
|
if length > 0 then
|
|
local bytes = base64_encode(string.sub(str, offset, offset+length))
|
|
self.trans:write(bytes)
|
|
end
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONInteger(num)
|
|
self:writeElemSeparator()
|
|
if self:escapeNum() then
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
end
|
|
local numstr = "" .. num
|
|
numstr = string.sub(numstr, string.find(numstr, "^[+-]?%d+"))
|
|
self.trans:write(numstr)
|
|
if self:escapeNum() then
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONDouble(dub)
|
|
self:writeElemSeparator()
|
|
local val = "" .. dub
|
|
local prefix = string.sub(val, 1, 1)
|
|
local special = false
|
|
if prefix == 'N' or prefix == 'n' then
|
|
val = JSONNode.Nan
|
|
special = true
|
|
elseif prefix == 'I' or prefix == 'i' then
|
|
val = JSONNode.Infinity
|
|
special = true
|
|
elseif prefix == '-' then
|
|
local secondByte = string.sub(val, 2, 2)
|
|
if secondByte == 'I' or secondByte == 'i' then
|
|
val = JSONNode.NegativeInfinity
|
|
special = true
|
|
end
|
|
end
|
|
|
|
if special or self:escapeNum() then
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
end
|
|
self.trans:write(val)
|
|
if special or self:escapeNum() then
|
|
self.trans:write(JSONNode.StringDelimiter)
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONObjectBegin()
|
|
self:writeElemSeparator()
|
|
self.trans:write(JSONNode.ObjectBegin)
|
|
self:contextPush({first = true, colon = true, ttype = 1, null = false})
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONObjectEnd()
|
|
self:contextPop()
|
|
self.trans:write(JSONNode.ObjectEnd)
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONArrayBegin()
|
|
self:writeElemSeparator()
|
|
self.trans:write(JSONNode.ArrayBegin)
|
|
self:contextPush({first = true, colon = true, ttype = 2, null = false})
|
|
end
|
|
|
|
function TJSONProtocol:writeJSONArrayEnd()
|
|
self:contextPop()
|
|
self.trans:write(JSONNode.ArrayEnd)
|
|
end
|
|
|
|
function TJSONProtocol:writeMessageBegin(name, ttype, seqid)
|
|
self:resetContext()
|
|
self:writeJSONArrayBegin()
|
|
self:writeJSONInteger(TJSONProtocol.THRIFT_JSON_PROTOCOL_VERSION)
|
|
self:writeJSONString(name)
|
|
self:writeJSONInteger(ttype)
|
|
self:writeJSONInteger(seqid)
|
|
end
|
|
|
|
function TJSONProtocol:writeMessageEnd()
|
|
self:writeJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:writeStructBegin(name)
|
|
self:writeJSONObjectBegin()
|
|
end
|
|
|
|
function TJSONProtocol:writeStructEnd()
|
|
self:writeJSONObjectEnd()
|
|
end
|
|
|
|
function TJSONProtocol:writeFieldBegin(name, ttype, id)
|
|
self:writeJSONInteger(id)
|
|
self:writeJSONObjectBegin()
|
|
self:writeJSONString(TTypeToString[ttype])
|
|
end
|
|
|
|
function TJSONProtocol:writeFieldEnd()
|
|
self:writeJSONObjectEnd()
|
|
end
|
|
|
|
function TJSONProtocol:writeFieldStop()
|
|
end
|
|
|
|
function TJSONProtocol:writeMapBegin(ktype, vtype, size)
|
|
self:writeJSONArrayBegin()
|
|
self:writeJSONString(TTypeToString[ktype])
|
|
self:writeJSONString(TTypeToString[vtype])
|
|
self:writeJSONInteger(size)
|
|
return self:writeJSONObjectBegin()
|
|
end
|
|
|
|
function TJSONProtocol:writeMapEnd()
|
|
self:writeJSONObjectEnd()
|
|
self:writeJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:writeListBegin(etype, size)
|
|
self:writeJSONArrayBegin()
|
|
self:writeJSONString(TTypeToString[etype])
|
|
self:writeJSONInteger(size)
|
|
end
|
|
|
|
function TJSONProtocol:writeListEnd()
|
|
self:writeJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:writeSetBegin(etype, size)
|
|
self:writeJSONArrayBegin()
|
|
self:writeJSONString(TTypeToString[etype])
|
|
self:writeJSONInteger(size)
|
|
end
|
|
|
|
function TJSONProtocol:writeSetEnd()
|
|
self:writeJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:writeBool(bool)
|
|
if bool then
|
|
self:writeJSONInteger(1)
|
|
else
|
|
self:writeJSONInteger(0)
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:writeByte(byte)
|
|
local buff = libluabpack.bpack('c', byte)
|
|
local val = libluabpack.bunpack('c', buff)
|
|
self:writeJSONInteger(val)
|
|
end
|
|
|
|
function TJSONProtocol:writeI16(i16)
|
|
local buff = libluabpack.bpack('s', i16)
|
|
local val = libluabpack.bunpack('s', buff)
|
|
self:writeJSONInteger(val)
|
|
end
|
|
|
|
function TJSONProtocol:writeI32(i32)
|
|
local buff = libluabpack.bpack('i', i32)
|
|
local val = libluabpack.bunpack('i', buff)
|
|
self:writeJSONInteger(val)
|
|
end
|
|
|
|
function TJSONProtocol:writeI64(i64)
|
|
local buff = libluabpack.bpack('l', i64)
|
|
local val = libluabpack.bunpack('l', buff)
|
|
self:writeJSONInteger(tostring(val))
|
|
end
|
|
|
|
function TJSONProtocol:writeDouble(dub)
|
|
self:writeJSONDouble(string.format("%.16f", dub))
|
|
end
|
|
|
|
function TJSONProtocol:writeString(str)
|
|
self:writeJSONString(str)
|
|
end
|
|
|
|
function TJSONProtocol:writeBinary(str)
|
|
-- Should be utf-8
|
|
self:writeJSONBase64(str)
|
|
end
|
|
|
|
function TJSONProtocol:readJSONSyntaxChar(ch)
|
|
local ch2 = ""
|
|
if self.hasReadByte ~= "" then
|
|
ch2 = self.hasReadByte
|
|
self.hasReadByte = ""
|
|
else
|
|
ch2 = self.trans:readAll(1)
|
|
end
|
|
if ch2 ~= ch then
|
|
terror(TProtocolException:new{message = "Expected ".. ch .. ", got " .. ch2})
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:readElemSeparator()
|
|
if self.jsonContextVal.null then
|
|
return
|
|
end
|
|
if self.jsonContextVal.first then
|
|
self.jsonContextVal.first = false
|
|
else
|
|
if self.jsonContextVal.ttype == 1 then
|
|
if self.jsonContextVal.colon then
|
|
self:readJSONSyntaxChar(JSONNode.PairSeparator)
|
|
self.jsonContextVal.colon = false
|
|
else
|
|
self:readJSONSyntaxChar(JSONNode.ElemSeparator)
|
|
self.jsonContextVal.colon = true
|
|
end
|
|
else
|
|
self:readJSONSyntaxChar(JSONNode.ElemSeparator)
|
|
end
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:hexVal(ch)
|
|
local val = string.byte(ch)
|
|
if val >= 48 and val <= 57 then
|
|
return val - 48
|
|
elseif val >= 97 and val <= 102 then
|
|
return val - 87
|
|
else
|
|
terror(TProtocolException:new{message = "Expected hex val ([0-9a-f]); got " .. ch})
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:readJSONEscapeChar(ch)
|
|
self:readJSONSyntaxChar(JSONNode.ZeroChar)
|
|
self:readJSONSyntaxChar(JSONNode.ZeroChar)
|
|
local b1 = self.trans:readAll(1)
|
|
local b2 = self.trans:readAll(1)
|
|
return libluabitwise.shiftl(self:hexVal(b1), 4) + self:hexVal(b2)
|
|
end
|
|
|
|
|
|
function TJSONProtocol:readJSONString()
|
|
self:readElemSeparator()
|
|
self:readJSONSyntaxChar(JSONNode.StringDelimiter)
|
|
local result = ""
|
|
while true do
|
|
local ch = self.trans:readAll(1)
|
|
if ch == JSONNode.StringDelimiter then
|
|
break
|
|
end
|
|
if ch == JSONNode.Backslash then
|
|
ch = self.trans:readAll(1)
|
|
if ch == JSONNode.EscapeChar then
|
|
self:readJSONEscapeChar(ch)
|
|
else
|
|
local pos, _ = string.find(JSONNode.EscapeChars, ch)
|
|
if pos == nil then
|
|
terror(TProtocolException:new{message = "Expected control char, got " .. ch})
|
|
end
|
|
ch = EscapeCharVals[pos]
|
|
end
|
|
end
|
|
result = result .. ch
|
|
end
|
|
return result
|
|
end
|
|
|
|
function TJSONProtocol:readJSONBase64()
|
|
local result = self:readJSONString()
|
|
local length = string.len(result)
|
|
local str = ""
|
|
local offset = 1
|
|
while length >= 4 do
|
|
local bytes = string.sub(result, offset, offset+4)
|
|
str = str .. base64_decode(bytes)
|
|
offset = offset + 4
|
|
length = length - 4
|
|
end
|
|
if length >= 0 then
|
|
str = str .. base64_decode(string.sub(result, offset, offset + length))
|
|
end
|
|
return str
|
|
end
|
|
|
|
function TJSONProtocol:readJSONNumericChars()
|
|
local result = ""
|
|
while true do
|
|
local ch = self.trans:readAll(1)
|
|
if string.find(ch, '[-+0-9.Ee]') then
|
|
result = result .. ch
|
|
else
|
|
self.hasReadByte = ch
|
|
break
|
|
end
|
|
end
|
|
return result
|
|
end
|
|
|
|
function TJSONProtocol:readJSONLongInteger()
|
|
self:readElemSeparator()
|
|
if self:escapeNum() then
|
|
self:readJSONSyntaxChar(JSONNode.StringDelimiter)
|
|
end
|
|
local result = self:readJSONNumericChars()
|
|
if self:escapeNum() then
|
|
self:readJSONSyntaxChar(JSONNode.StringDelimiter)
|
|
end
|
|
return result
|
|
end
|
|
|
|
function TJSONProtocol:readJSONInteger()
|
|
return tonumber(self:readJSONLongInteger())
|
|
end
|
|
|
|
function TJSONProtocol:readJSONDouble()
|
|
self:readElemSeparator()
|
|
local delimiter = self.trans:readAll(1)
|
|
local num = 0.0
|
|
if delimiter == JSONNode.StringDelimiter then
|
|
local str = self:readJSONString()
|
|
if str == JSONNode.Nan then
|
|
num = 1.0
|
|
elseif str == JSONNode.Infinity then
|
|
num = math.maxinteger
|
|
elseif str == JSONNode.NegativeInfinity then
|
|
num = math.mininteger
|
|
else
|
|
num = tonumber(str)
|
|
end
|
|
else
|
|
if self:escapeNum() then
|
|
self:readJSONSyntaxChar(JSONNode.StringDelimiter)
|
|
end
|
|
local result = self:readJSONNumericChars()
|
|
num = tonumber(delimiter.. result)
|
|
end
|
|
return num
|
|
end
|
|
|
|
function TJSONProtocol:readJSONObjectBegin()
|
|
self:readElemSeparator()
|
|
self:readJSONSyntaxChar(JSONNode.ObjectBegin)
|
|
self:contextPush({first = true, colon = true, ttype = 1, null = false})
|
|
end
|
|
|
|
function TJSONProtocol:readJSONObjectEnd()
|
|
self:readJSONSyntaxChar(JSONNode.ObjectEnd)
|
|
self:contextPop()
|
|
end
|
|
|
|
function TJSONProtocol:readJSONArrayBegin()
|
|
self:readElemSeparator()
|
|
self:readJSONSyntaxChar(JSONNode.ArrayBegin)
|
|
self:contextPush({first = true, colon = true, ttype = 2, null = false})
|
|
end
|
|
|
|
function TJSONProtocol:readJSONArrayEnd()
|
|
self:readJSONSyntaxChar(JSONNode.ArrayEnd)
|
|
self:contextPop()
|
|
end
|
|
|
|
function TJSONProtocol:readMessageBegin()
|
|
self:resetContext()
|
|
self:readJSONArrayBegin()
|
|
local version = self:readJSONInteger()
|
|
if version ~= self.THRIFT_JSON_PROTOCOL_VERSION then
|
|
terror(TProtocolException:new{message = "Message contained bad version."})
|
|
end
|
|
local name = self:readJSONString()
|
|
local ttype = self:readJSONInteger()
|
|
local seqid = self:readJSONInteger()
|
|
return name, ttype, seqid
|
|
end
|
|
|
|
function TJSONProtocol:readMessageEnd()
|
|
self:readJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:readStructBegin()
|
|
self:readJSONObjectBegin()
|
|
return nil
|
|
end
|
|
|
|
function TJSONProtocol:readStructEnd()
|
|
self:readJSONObjectEnd()
|
|
end
|
|
|
|
function TJSONProtocol:readFieldBegin()
|
|
local ttype = TType.STOP
|
|
local id = 0
|
|
local ch = self.trans:readAll(1)
|
|
self.hasReadByte = ch
|
|
if ch ~= JSONNode.ObjectEnd then
|
|
id = self:readJSONInteger()
|
|
self:readJSONObjectBegin()
|
|
local typeName = self:readJSONString()
|
|
ttype = StringToTType[typeName]
|
|
end
|
|
return nil, ttype, id
|
|
end
|
|
|
|
function TJSONProtocol:readFieldEnd()
|
|
self:readJSONObjectEnd()
|
|
end
|
|
|
|
function TJSONProtocol:readMapBegin()
|
|
self:readJSONArrayBegin()
|
|
local typeName = self:readJSONString()
|
|
local ktype = StringToTType[typeName]
|
|
typeName = self:readJSONString()
|
|
local vtype = StringToTType[typeName]
|
|
local size = self:readJSONInteger()
|
|
self:readJSONObjectBegin()
|
|
return ktype, vtype, size
|
|
end
|
|
|
|
function TJSONProtocol:readMapEnd()
|
|
self:readJSONObjectEnd()
|
|
self:readJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:readListBegin()
|
|
self:readJSONArrayBegin()
|
|
local typeName = self:readJSONString()
|
|
local etype = StringToTType[typeName]
|
|
local size = self:readJSONInteger()
|
|
return etype, size
|
|
end
|
|
|
|
function TJSONProtocol:readListEnd()
|
|
return self:readJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:readSetBegin()
|
|
return self:readListBegin()
|
|
end
|
|
|
|
function TJSONProtocol:readSetEnd()
|
|
return self:readJSONArrayEnd()
|
|
end
|
|
|
|
function TJSONProtocol:readBool()
|
|
local result = self:readJSONInteger()
|
|
if result == 1 then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function TJSONProtocol:readByte()
|
|
local result = self:readJSONInteger()
|
|
if result >= 256 then
|
|
terror(TProtocolException:new{message = "UnExpected Byte " .. result})
|
|
end
|
|
return result
|
|
end
|
|
|
|
function TJSONProtocol:readI16()
|
|
return self:readJSONInteger()
|
|
end
|
|
|
|
function TJSONProtocol:readI32()
|
|
return self:readJSONInteger()
|
|
end
|
|
|
|
function TJSONProtocol:readI64()
|
|
local long = liblualongnumber.new
|
|
return long(self:readJSONLongInteger())
|
|
end
|
|
|
|
function TJSONProtocol:readDouble()
|
|
return self:readJSONDouble()
|
|
end
|
|
|
|
function TJSONProtocol:readString()
|
|
return self:readJSONString()
|
|
end
|
|
|
|
function TJSONProtocol:readBinary()
|
|
return self:readJSONBase64()
|
|
end
|
|
|
|
TJSONProtocolFactory = TProtocolFactory:new{
|
|
__type = 'TJSONProtocolFactory',
|
|
}
|
|
|
|
function TJSONProtocolFactory: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 TJSONProtocol:new{
|
|
trans = trans
|
|
}
|
|
end
|