You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

355 lines
11 KiB

  1. local bit = require("luaScript.ModuleEapSdk.EapFunc.websocket.bit")
  2. -- local ffi = require'ffi'
  3. local proto = {}
  4. -- return base 128 varint string
  5. function proto.serializeVarint(i)
  6. assert(math.fmod(i, 1) == 0)
  7. local result = {}
  8. while true do
  9. local b = bit.band(i, 0x7F)
  10. i = bit.rshift(i, 7)
  11. if i ~= 0 then -- has more
  12. table.insert(result, bit.bor(0x80, b))
  13. else
  14. table.insert(result, b)
  15. break
  16. end
  17. end
  18. return string.char(unpack(result))
  19. end
  20. -- return value and next index
  21. function proto.parseVarint(buff, index)
  22. assert(type(buff) == "string" and index > 0)
  23. local result = 0;
  24. local current = index
  25. while true do
  26. local thisByte = string.byte(buff, current)
  27. local thisByte2 = bit.band(0x7F, thisByte)
  28. result = bit.bor(result, bit.lshift(thisByte2, 7*(current-index)))
  29. current = current + 1
  30. if bit.band(thisByte, 0x80) == 0 then break end
  31. end
  32. return result, current
  33. end
  34. -- ffi.cdef[[
  35. -- union bar { uint8_t b[8]; double d; };
  36. -- union bar1 { uint8_t b[4]; float d; };
  37. -- union myuint64 { uint8_t b[8]; uint64_t d; };
  38. -- ]]
  39. --- return 8-byte string with same memory layout from double "d"
  40. function proto.serializeDouble(dbl)
  41. -- local u = ffi.new("union bar", {d=dbl})
  42. -- local v = u.b
  43. -- return string.char(v[0], v[1], v[2], v[3],
  44. -- v[4], v[5], v[6], v[7])
  45. end
  46. function proto.parseDouble(buff, index)
  47. -- assert(index+7 <= #buff)
  48. -- local u = ffi.new("union bar")
  49. -- local v = u.b
  50. -- v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7] = string.byte(buff, index, index+7)
  51. -- return u.d, index+8
  52. end
  53. function proto.parseFloat(buff, index)
  54. -- assert(index+3 <= #buff)
  55. -- local u = ffi.new("union bar1")
  56. -- local v = u.b
  57. -- v[0], v[1], v[2], v[3] = string.byte(buff, index, index+3)
  58. -- return u.d, index+4
  59. local h1,h2,h3,h4 = string.byte(buff, index, index+3)
  60. print("proto.parseFloat = ", h1, h2, h3, h4)
  61. local hexNum = bit.lshift(h4, 24) + bit.lshift(h3, 16) + bit.lshift(h2, 8) + h1
  62. -- local hexNum = bit.lshift(h1, 24) + bit.lshift(h2, 16) + bit.lshift(h3, 8) + h4
  63. local res = proto.DatToFloat(hexNum)
  64. return res, index+4
  65. end
  66. -- return tag, wire type
  67. function proto.extractKey(k)
  68. return bit.rshift(k, 3), bit.band(k, 0x7)
  69. end
  70. function proto.findName(tag, prt)
  71. for k, v in pairs(prt) do
  72. if v[1] == tag then return k end
  73. end
  74. return nil
  75. end
  76. -- tbl: table value to be serialized
  77. -- prt: protobuf description table
  78. -- return: a string with serialized value
  79. --
  80. -- detailed mapping
  81. -- lua type | prontobuf type
  82. -- string | length-delimited (1)
  83. -- double | 64-bit (2)
  84. -- int | varint (0)
  85. -- note, there is no "int" in lua,
  86. -- only when math.fmod(x, 1) == 0
  87. function proto.serialize(tbl, prt)
  88. assert(tbl and prt)
  89. local result = {}
  90. for k, v in pairs(tbl) do
  91. local isRepeat = false -- repeated string like
  92. local t = type(v)
  93. local tag = prt[k][1]
  94. local ext = prt[k][3]
  95. if not tag then
  96. assert(false, "can't find " .. k .. " in proto")
  97. end
  98. local key, value
  99. if t == "string" then
  100. key = bit.bor(bit.lshift(tag, 3), 2)
  101. key = proto.serializeVarint(key)
  102. value = proto.serializeVarint(#v) .. v
  103. elseif t == "number" then
  104. if math.fmod(v, 1) == 0 then
  105. -- varint
  106. if prt[k][2] == "sint32" or prt[k][2] == "sint64" then
  107. v = 2*v
  108. if v < 0 then
  109. -- v = v - 1
  110. v = math.abs(v)-1
  111. end
  112. end
  113. key = bit.bor(bit.lshift(tag, 3), 0)
  114. key = proto.serializeVarint(key)
  115. value = proto.serializeVarint(v)
  116. else
  117. -- double
  118. key = bit.bor(bit.lshift(tag, 3), 1)
  119. key = proto.serializeVarint(key)
  120. value = proto.serializeDouble(v)
  121. end
  122. elseif t == "boolean" then
  123. key = bit.bor(bit.lshift(tag, 3), 0)
  124. key = proto.serializeVarint(key)
  125. value = proto.serializeVarint(1)
  126. elseif t == "table" then
  127. if ext and ext == "repeated" then
  128. print("proto serialize vector packed")
  129. if #v > 0 then
  130. local subType = type(v[1])
  131. if subType == "number" then
  132. local zigZag = false
  133. if prt[k][2] == "sint32" or prt[k][2] == "sint64" then
  134. zigZag = true
  135. end
  136. local v_totalLen = 0
  137. for k2=1, #v do
  138. local v2 = v[k2]
  139. if zigZag then
  140. v2 = 2*v2
  141. if v2 < 0 then
  142. v2 = math.abs(v2)-1
  143. end
  144. end
  145. local itemValue = proto.serializeVarint(v2)
  146. v_totalLen = v_totalLen + #itemValue
  147. end
  148. local itemValue = proto.serializeVarint(v[1])
  149. key = bit.bor(bit.lshift(tag, 3), 2)
  150. key = proto.serializeVarint(key)
  151. value = proto.serializeVarint(v_totalLen)
  152. for k1, v1 in pairs(v) do
  153. if zigZag then
  154. v1 = 2*v1
  155. if v1 < 0 then
  156. v1 = math.abs(v1)-1
  157. end
  158. end
  159. local tmpValue = proto.serializeVarint(v1)
  160. value = value..tmpValue
  161. end
  162. elseif subType == "string" then
  163. isRepeat = true
  164. for k1, v1 in pairs(v) do
  165. key = bit.bor(bit.lshift(tag, 3), 2)
  166. key = proto.serializeVarint(key)
  167. value = proto.serializeVarint(#v1) .. v1
  168. table.insert(result, key .. value)
  169. end
  170. end
  171. end
  172. else
  173. local subPrt = G_EapProtos[prt[k][2]] -- embedded messages
  174. if subPrt then
  175. local v1 = proto.serialize(v, subPrt)
  176. key = bit.bor(bit.lshift(tag, 3), 2)
  177. key = proto.serializeVarint(key)
  178. value = proto.serializeVarint(#v1) .. v1
  179. else
  180. print("can't serilize table embedded " .. prt[k][2])
  181. end
  182. end
  183. else
  184. print(false, "can't support " .. t)
  185. end
  186. if not isRepeat then
  187. table.insert(result, key .. value)
  188. end
  189. end
  190. return table.concat(result)
  191. end
  192. -- str: a string value with serialized value
  193. -- prt: protobuf
  194. -- return: a parsed table value
  195. function proto.parse(str, prt)
  196. local result = {}
  197. local len = string.len(str)
  198. local index = 1
  199. while index <= len do
  200. local key
  201. key, index = proto.parseVarint(str, index)
  202. local tag, wire_type = proto.extractKey(key)
  203. local value
  204. local tagName = proto.findName(tag, prt)
  205. local prtInfo = prt[tagName]
  206. if wire_type == 0 then
  207. if prtInfo then
  208. value, index = proto.parseVarint(str, index)
  209. end
  210. elseif wire_type == 1 then
  211. value, index = proto.parseDouble(str, index)
  212. elseif wire_type == 2 then
  213. local len
  214. len, index = proto.parseVarint(str, index)
  215. value = string.sub(str, index, index+len-1)
  216. index = index + len
  217. elseif wire_type == 5 then
  218. value, index = proto.parseFloat(str, index)
  219. else
  220. print(false, "doesn't support wire type " .. wire_type)
  221. end
  222. -- set pair in table
  223. if prtInfo then
  224. if prtInfo[2] == "sint32" or prtInfo[2] == "sint64" then
  225. if type(value) == "number" then
  226. if value%2 == 0 then
  227. value = value/2
  228. else
  229. value = -(value+1)/2
  230. end
  231. end
  232. else
  233. local subPrt = G_EapProtos[prtInfo[2]] -- embedded messages
  234. if subPrt then
  235. value = proto.parse(value, subPrt)
  236. end
  237. end
  238. -- repeated embedded messages
  239. if prtInfo[3] and prtInfo[3] == "repeated" then
  240. result[tagName] = result[tagName] or {}
  241. end
  242. end
  243. if tagName and value then
  244. if type(result[tagName]) == "table" then
  245. result[tagName][#result[tagName] + 1] = value
  246. else
  247. result[tagName] = value
  248. end
  249. else
  250. print(false, "can't find the name : ")
  251. end
  252. end
  253. return result
  254. end
  255. function proto.int16ToBufStr(num)
  256. local str = "";
  257. str = str .. string.char(bit.rshift(num, 8));
  258. str = str .. string.char(bit.band(num, 0x00FF));
  259. return str;
  260. end
  261. function proto.buffToInt16(num1, num2)
  262. return bit.lshift(num1, 8) + num2
  263. end
  264. function proto.hexToFloat( hexNums )
  265. local sign = math.modf(hexNums/(2^31))
  266. local exponent = hexNums % (2^31)
  267. exponent = math.modf(exponent/(2^23)) -127
  268. local mantissa = hexNums % (2^23)
  269. for i=1,23 do
  270. mantissa = mantissa / 2
  271. end
  272. mantissa = 1+mantissa
  273. local result = (-1)^sign * mantissa * 2^exponent
  274. return result
  275. end
  276. function DatToFloat1(x)
  277. local temp
  278. local aa = 8388608
  279. local s = bit.rshift(bit.band(x, 0x80000000), 31)--(x & 0x80000000)>>31
  280. local e = bit.rshift(bit.band(x, 0x7F800000), 23)--(x & 0x7F800000)>>23
  281. temp = bit.band(x, 0X7FFFFF) / aa--(x&0X7FFFFF)/aa
  282. local res = bit.lshift(e-127, 1) * (1+temp)--(1<<(e-127)) * (1+temp)
  283. if s==1 then res = 0-res end
  284. return res
  285. end
  286. function pow(n)
  287. local temp =1
  288. for m =1, n do
  289. temp = temp * 0.5
  290. end
  291. return temp
  292. end
  293. function DatToFloat2(x)
  294. local s = bit.rshift(bit.band(x, 0x80000000), 31)--(x & 0x80000000)>>31
  295. local e = bit.rshift(bit.band(x, 0x7F800000), 23)--(x & 0x7F800000)>>23
  296. local m = 127-e
  297. local temp = pow(m)
  298. local weishu = bit.band(x, 0x7FFFFF)--x & 0x7FFFFF
  299. local sum = 0
  300. local j = 23+m
  301. local weishutemp = bit.bxor(weishu, bit.lshift(0x1, 23))--weishu ~ (0x1<<23)
  302. for m = 1, 24 do
  303. bitdat = bit.band(weishutemp, 0x1)--weishutemp & 0x1
  304. if bitdat == 1 then sum = sum + pow(j) end
  305. weishutemp = bit.rshift(weishutemp, 1)--weishutemp >>1
  306. j = j -1
  307. end
  308. if s==1 then sum = 0-sum end
  309. return sum
  310. end
  311. function proto.DatToFloat(x)
  312. local result
  313. local e = bit.rshift(bit.band(x, 0x7F800000), 23)--(x & 0x7F800000)>>23
  314. if e==255 and bit.band(x, 0x7FFFFF) == 0 then return "InF" end
  315. if e==255 and bit.band(x, 0x7FFFFF) ~= 0 then return "NaN" end
  316. if e>=128 then
  317. result = DatToFloat1(x)
  318. else
  319. result = DatToFloat2(x)
  320. end
  321. return result
  322. end
  323. return proto