MarkdownPreviewer/lua/MarkdownPreviewer/msgpack.lua
2025-08-18 23:02:07 +02:00

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