|
- local bit = require("luaScript.ModuleEapSdk.EapFunc.websocket.bit")
- -- local ffi = require'ffi'
-
- local proto = {}
-
- -- return base 128 varint string
- function proto.serializeVarint(i)
- assert(math.fmod(i, 1) == 0)
- local result = {}
-
- while true do
- local b = bit.band(i, 0x7F)
- i = bit.rshift(i, 7)
- if i ~= 0 then -- has more
- table.insert(result, bit.bor(0x80, b))
- else
- table.insert(result, b)
- break
- end
- end
- return string.char(unpack(result))
- end
-
- -- return value and next index
- function proto.parseVarint(buff, index)
- assert(type(buff) == "string" and index > 0)
- local result = 0;
- local current = index
- while true do
- local thisByte = string.byte(buff, current)
- local thisByte2 = bit.band(0x7F, thisByte)
- result = bit.bor(result, bit.lshift(thisByte2, 7*(current-index)))
- current = current + 1
- if bit.band(thisByte, 0x80) == 0 then break end
- end
- return result, current
- end
-
- -- ffi.cdef[[
- -- union bar { uint8_t b[8]; double d; };
- -- union bar1 { uint8_t b[4]; float d; };
- -- union myuint64 { uint8_t b[8]; uint64_t d; };
- -- ]]
-
- --- return 8-byte string with same memory layout from double "d"
- function proto.serializeDouble(dbl)
- -- local u = ffi.new("union bar", {d=dbl})
- -- local v = u.b
- -- return string.char(v[0], v[1], v[2], v[3],
- -- v[4], v[5], v[6], v[7])
- end
-
- function proto.parseDouble(buff, index)
- -- assert(index+7 <= #buff)
- -- local u = ffi.new("union bar")
- -- local v = u.b
- -- v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7] = string.byte(buff, index, index+7)
- -- return u.d, index+8
- end
-
- function proto.parseFloat(buff, index)
- -- assert(index+3 <= #buff)
- -- local u = ffi.new("union bar1")
- -- local v = u.b
- -- v[0], v[1], v[2], v[3] = string.byte(buff, index, index+3)
- -- return u.d, index+4
- local h1,h2,h3,h4 = string.byte(buff, index, index+3)
- print("proto.parseFloat = ", h1, h2, h3, h4)
- local hexNum = bit.lshift(h4, 24) + bit.lshift(h3, 16) + bit.lshift(h2, 8) + h1
- -- local hexNum = bit.lshift(h1, 24) + bit.lshift(h2, 16) + bit.lshift(h3, 8) + h4
- local res = proto.DatToFloat(hexNum)
-
- return res, index+4
- end
-
- -- return tag, wire type
- function proto.extractKey(k)
- return bit.rshift(k, 3), bit.band(k, 0x7)
- end
-
-
- function proto.findName(tag, prt)
- for k, v in pairs(prt) do
- if v[1] == tag then return k end
- end
- return nil
- end
- -- tbl: table value to be serialized
- -- prt: protobuf description table
- -- return: a string with serialized value
- --
- -- detailed mapping
- -- lua type | prontobuf type
- -- string | length-delimited (1)
- -- double | 64-bit (2)
- -- int | varint (0)
-
- -- note, there is no "int" in lua,
- -- only when math.fmod(x, 1) == 0
- function proto.serialize(tbl, prt)
- assert(tbl and prt)
- local result = {}
- for k, v in pairs(tbl) do
- local isRepeat = false -- repeated string like
- local t = type(v)
- local tag = prt[k][1]
- local ext = prt[k][3]
- if not tag then
- assert(false, "can't find " .. k .. " in proto")
- end
- local key, value
- if t == "string" then
- key = bit.bor(bit.lshift(tag, 3), 2)
- key = proto.serializeVarint(key)
- value = proto.serializeVarint(#v) .. v
- elseif t == "number" then
- if math.fmod(v, 1) == 0 then
- -- varint
- if prt[k][2] == "sint32" or prt[k][2] == "sint64" then
- v = 2*v
- if v < 0 then
- -- v = v - 1
- v = math.abs(v)-1
- end
- end
- key = bit.bor(bit.lshift(tag, 3), 0)
- key = proto.serializeVarint(key)
- value = proto.serializeVarint(v)
- else
- -- double
- key = bit.bor(bit.lshift(tag, 3), 1)
- key = proto.serializeVarint(key)
- value = proto.serializeDouble(v)
- end
- elseif t == "boolean" then
- key = bit.bor(bit.lshift(tag, 3), 0)
- key = proto.serializeVarint(key)
- value = proto.serializeVarint(1)
- elseif t == "table" then
- if ext and ext == "repeated" then
- print("proto serialize vector packed")
- if #v > 0 then
- local subType = type(v[1])
- if subType == "number" then
- local zigZag = false
- if prt[k][2] == "sint32" or prt[k][2] == "sint64" then
- zigZag = true
- end
- local v_totalLen = 0
- for k2=1, #v do
- local v2 = v[k2]
- if zigZag then
- v2 = 2*v2
- if v2 < 0 then
- v2 = math.abs(v2)-1
- end
- end
- local itemValue = proto.serializeVarint(v2)
- v_totalLen = v_totalLen + #itemValue
- end
- local itemValue = proto.serializeVarint(v[1])
- key = bit.bor(bit.lshift(tag, 3), 2)
- key = proto.serializeVarint(key)
- value = proto.serializeVarint(v_totalLen)
-
- for k1, v1 in pairs(v) do
- if zigZag then
- v1 = 2*v1
- if v1 < 0 then
- v1 = math.abs(v1)-1
- end
- end
- local tmpValue = proto.serializeVarint(v1)
- value = value..tmpValue
- end
- elseif subType == "string" then
- isRepeat = true
- for k1, v1 in pairs(v) do
- key = bit.bor(bit.lshift(tag, 3), 2)
- key = proto.serializeVarint(key)
- value = proto.serializeVarint(#v1) .. v1
- table.insert(result, key .. value)
- end
- end
- end
- else
- local subPrt = G_EapProtos[prt[k][2]] -- embedded messages
- if subPrt then
- local v1 = proto.serialize(v, subPrt)
- key = bit.bor(bit.lshift(tag, 3), 2)
- key = proto.serializeVarint(key)
- value = proto.serializeVarint(#v1) .. v1
- else
- print("can't serilize table embedded " .. prt[k][2])
- end
- end
- else
- print(false, "can't support " .. t)
- end
- if not isRepeat then
- table.insert(result, key .. value)
- end
- end
- return table.concat(result)
- end
-
- -- str: a string value with serialized value
- -- prt: protobuf
- -- return: a parsed table value
- function proto.parse(str, prt)
- local result = {}
- local len = string.len(str)
- local index = 1
- while index <= len do
- local key
- key, index = proto.parseVarint(str, index)
- local tag, wire_type = proto.extractKey(key)
- local value
- local tagName = proto.findName(tag, prt)
- local prtInfo = prt[tagName]
- if wire_type == 0 then
- if prtInfo then
- value, index = proto.parseVarint(str, index)
- end
- elseif wire_type == 1 then
- value, index = proto.parseDouble(str, index)
- elseif wire_type == 2 then
- local len
- len, index = proto.parseVarint(str, index)
- value = string.sub(str, index, index+len-1)
- index = index + len
- elseif wire_type == 5 then
- value, index = proto.parseFloat(str, index)
- else
- print(false, "doesn't support wire type " .. wire_type)
- end
- -- set pair in table
- if prtInfo then
- if prtInfo[2] == "sint32" or prtInfo[2] == "sint64" then
- if type(value) == "number" then
- if value%2 == 0 then
- value = value/2
- else
- value = -(value+1)/2
- end
- end
- else
- local subPrt = G_EapProtos[prtInfo[2]] -- embedded messages
- if subPrt then
- value = proto.parse(value, subPrt)
- end
- end
- -- repeated embedded messages
- if prtInfo[3] and prtInfo[3] == "repeated" then
- result[tagName] = result[tagName] or {}
- end
- end
- if tagName and value then
- if type(result[tagName]) == "table" then
- result[tagName][#result[tagName] + 1] = value
- else
- result[tagName] = value
- end
- else
- print(false, "can't find the name : ")
- end
- end
- return result
- end
-
- function proto.int16ToBufStr(num)
- local str = "";
- str = str .. string.char(bit.rshift(num, 8));
- str = str .. string.char(bit.band(num, 0x00FF));
- return str;
- end
-
- function proto.buffToInt16(num1, num2)
- return bit.lshift(num1, 8) + num2
- end
-
- function proto.hexToFloat( hexNums )
- local sign = math.modf(hexNums/(2^31))
-
- local exponent = hexNums % (2^31)
- exponent = math.modf(exponent/(2^23)) -127
-
- local mantissa = hexNums % (2^23)
-
- for i=1,23 do
- mantissa = mantissa / 2
- end
- mantissa = 1+mantissa
- local result = (-1)^sign * mantissa * 2^exponent
- return result
- end
-
- function DatToFloat1(x)
- local temp
- local aa = 8388608
- local s = bit.rshift(bit.band(x, 0x80000000), 31)--(x & 0x80000000)>>31
- local e = bit.rshift(bit.band(x, 0x7F800000), 23)--(x & 0x7F800000)>>23
- temp = bit.band(x, 0X7FFFFF) / aa--(x&0X7FFFFF)/aa
-
- local res = bit.lshift(e-127, 1) * (1+temp)--(1<<(e-127)) * (1+temp)
- if s==1 then res = 0-res end
- return res
- end
-
- function pow(n)
- local temp =1
- for m =1, n do
- temp = temp * 0.5
- end
- return temp
- end
-
- function DatToFloat2(x)
- local s = bit.rshift(bit.band(x, 0x80000000), 31)--(x & 0x80000000)>>31
- local e = bit.rshift(bit.band(x, 0x7F800000), 23)--(x & 0x7F800000)>>23
- local m = 127-e
- local temp = pow(m)
- local weishu = bit.band(x, 0x7FFFFF)--x & 0x7FFFFF
- local sum = 0
- local j = 23+m
- local weishutemp = bit.bxor(weishu, bit.lshift(0x1, 23))--weishu ~ (0x1<<23)
-
- for m = 1, 24 do
- bitdat = bit.band(weishutemp, 0x1)--weishutemp & 0x1
- if bitdat == 1 then sum = sum + pow(j) end
- weishutemp = bit.rshift(weishutemp, 1)--weishutemp >>1
- j = j -1
- end
-
- if s==1 then sum = 0-sum end
- return sum
- end
-
- function proto.DatToFloat(x)
-
- local result
- local e = bit.rshift(bit.band(x, 0x7F800000), 23)--(x & 0x7F800000)>>23
- if e==255 and bit.band(x, 0x7FFFFF) == 0 then return "InF" end
- if e==255 and bit.band(x, 0x7FFFFF) ~= 0 then return "NaN" end
-
- if e>=128 then
- result = DatToFloat1(x)
- else
- result = DatToFloat2(x)
- end
- return result
- end
-
- return proto
|