184 lines
4.8 KiB
Lua
184 lines
4.8 KiB
Lua
module = {}
|
|
|
|
local bit8 = 256
|
|
local bit16 = 65535
|
|
local bit32 = 4294967295
|
|
local bit64 = 18446744070000001024
|
|
|
|
local function ToUint16(length)
|
|
local len = length
|
|
t = {}
|
|
for i=2,1,-1 do
|
|
t[i] = math.fmod(len,256)
|
|
len = math.floor(len / 256)
|
|
end
|
|
return string.char(unpack(t))
|
|
end
|
|
|
|
local function ToUint32(length)
|
|
local len = length
|
|
t = {}
|
|
for i=4,1,-1 do
|
|
t[i] = math.fmod(len,256)
|
|
len = math.floor(len / 256)
|
|
end
|
|
return string.char(unpack(t))
|
|
end
|
|
|
|
local function ToUint64(length)
|
|
local len = length
|
|
t = {}
|
|
for i=8,1,-1 do
|
|
t[i] = math.fmod(len,256)
|
|
len = math.floor(len / 256)
|
|
end
|
|
return string.char(unpack(t))
|
|
end
|
|
|
|
local function is_array(t)
|
|
return type(t) == 'table' and (#t > 0 or next(t) == nil)
|
|
end
|
|
|
|
local function NilToMsgPack()
|
|
return string.char(0xc0)
|
|
end
|
|
|
|
local function StringToMsgPack(operand)
|
|
local str_len = #operand
|
|
|
|
if str_len <= 31 then
|
|
local header = string.char(0xa0 + str_len)
|
|
return header .. operand
|
|
elseif str_len <= bit8 - 1 then
|
|
local header = string.char(0xd9)
|
|
return header .. string.char(str_len) .. operand
|
|
elseif str_len <= bit16 - 1 then
|
|
local header = string.char(0xda)
|
|
return header .. ToUint16(str_len) .. operand
|
|
elseif str_len <= bit32 - 1 then
|
|
local header = string.char(0xdb)
|
|
return header .. ToUint32(str_len) .. operand
|
|
else
|
|
print("String too large")
|
|
return nil
|
|
end
|
|
end
|
|
|
|
local function NumberToMsgPack(operand)
|
|
if operand > 0 then
|
|
if operand <= 127 then
|
|
return string.char(operand)
|
|
elseif operand <= bit8 - 1 then
|
|
return string.char(0xcc) .. string.char(operand)
|
|
elseif operand <= bit16 - 1 then
|
|
return string.char(0xcd) .. ToUint16(operand)
|
|
elseif operand <= bit32 - 1 then
|
|
return string.char(0xce) .. ToUint32(operand)
|
|
elseif operand <= bit64 - 1 then
|
|
return string.char(0xcf) .. ToUint64(operand)
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
local function ArrayToMsgPack(operand)
|
|
local len = #operand
|
|
|
|
local data = ""
|
|
|
|
if len <= 15 then
|
|
data = data .. string.char(0x90 + len)
|
|
elseif len <= bit16 - 1 then
|
|
data = data .. string.char(0xdc) .. ToUint16(len)
|
|
elseif len <= bit32 - 1 then
|
|
data = data .. string.char(0xdd) .. ToUint32(len)
|
|
end
|
|
|
|
for i=1,len do
|
|
local element = operand[i]
|
|
if type(element) == 'nil' then
|
|
data = data .. NilToMsgPack()
|
|
elseif type(element) == 'number' then
|
|
data = data .. NumberToMsgPack(element)
|
|
elseif type(element) == 'string' then
|
|
data = data .. StringToMsgPack(element)
|
|
elseif type(element) == 'table' then
|
|
if is_array(element) then
|
|
data = data .. ArrayToMsgPack(element)
|
|
else
|
|
data = data .. TableToMsgPack(element)
|
|
end
|
|
end
|
|
end
|
|
|
|
return data
|
|
end
|
|
|
|
local function TableToMsgPack(operand)
|
|
local len = 0
|
|
for _,v in pairs(operand) do
|
|
len = len + 1
|
|
end
|
|
|
|
local data = ""
|
|
|
|
if len <= 15 then
|
|
data = data .. string.char(0x80 + len)
|
|
elseif len <= bit16 - 1 then
|
|
data = data .. string.char(0xde) .. ToUint16(len)
|
|
elseif len <= bit32 - 1 then
|
|
data = data .. string.char(0xdf) .. ToUint32(len)
|
|
end
|
|
|
|
for k,v in pairs(operand) do
|
|
if type(k) == 'nil' then
|
|
data = data .. NilToMsgPack()
|
|
elseif type(k) == 'number' then
|
|
data = data .. NumberToMsgPack(k)
|
|
elseif type(k) == 'string' then
|
|
data = data .. StringToMsgPack(k)
|
|
elseif type(k) == 'table' then
|
|
if is_array(k) then
|
|
data = data .. ArrayToMsgPack(k)
|
|
else
|
|
data = data .. TableToMsgPack(k)
|
|
end
|
|
end
|
|
|
|
if type(v) == 'nil' then
|
|
data = data .. NilToMsgPack()
|
|
elseif type(v) == 'number' then
|
|
data = data .. NumberToMsgPack(v)
|
|
elseif type(v) == 'string' then
|
|
data = data .. StringToMsgPack(v)
|
|
elseif type(v) == 'table' then
|
|
if is_array(v) then
|
|
data = data .. ArrayToMsgPack(v)
|
|
else
|
|
data = data .. TableToMsgPack(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
return data
|
|
end
|
|
|
|
function module.ToMsgPack(operand)
|
|
if type(operand) == 'nil' then
|
|
return NilToMsgPack()
|
|
elseif type(operand) == 'number' then
|
|
return NumberToMsgPack()
|
|
elseif type(operand) == 'string' then
|
|
return StringToMsgPack()
|
|
elseif type(operand) == 'table' then
|
|
if is_array(operand) then
|
|
return ArrayToMsgPack(operand)
|
|
else
|
|
return TableToMsgPack(operand)
|
|
end
|
|
end
|
|
end
|
|
|
|
return module
|