sokol-luajit/lua/msgpack-utils.lua

104 lines
3.1 KiB
Lua

local msgpack = require "lua.msgpack"
local uv = require("luv")
local TAG_START = "MSGPACK_START"
local TAG_END = "MSGPACK_END"
local TAG_START_LEN = #TAG_START + 1
local TAG_END_LEN = #TAG_END + 1
--------------------------------------------------------------------------------------------------
local function try_reader(fn, ...)
local err
local ok, res = xpcall(fn, function(msg)
local item = core.error("%s", msg)
item.info = debug.traceback(nil, 2):gsub("\t", "")
err = msg
end, ...)
if ok then
return true, res
end
return false, err
end
--------------------------------------------------------------------------------------------------
local function endsWith(str, suffix)
return str:sub(-#suffix) == suffix
end
--------------------------------------------------------------------------------------------------
local function startsWith(str, suffix)
return str:sub(1, #suffix) == suffix
end
--------------------------------------------------------------------------------------------------
-- Setup a read stream to process a message pack chunk of data
local function read_chunk(reader, output_func)
assert(reader, "msgpack reader should not be nil!!")
local reading = 0
local reading_done = nil
local total = ""
reader:read_start(function(err, chunk)
assert(not err, err)
if chunk == nil then
return
end
-- There may be multiple blocks to read within a single chunk!
if startsWith(chunk, TAG_START) then
chunk = string.sub(chunk, TAG_START_LEN)
reading = 1
for block in string.gmatch(chunk, string.format("%s(.-)%s", TAG_START, TAG_END)) do
if(output_func) then
-- print(total)
local data = msgpack.unpack(block)
output_func(data)
end
chunk = ""
end
end
if endsWith(chunk, TAG_END) then
chunk = string.sub(chunk, 1, -TAG_END_LEN)
reading_done = true
end
reading = reading + 1
if(reading > 0) then
total = total..chunk
end
if(reading_done) then
if(output_func) then
-- print(total)
local data = msgpack.unpack(total)
output_func(data)
end
reading_done = nil
total = ""
reading = 0
end
end)
end
--------------------------------------------------------------------------------------------------
local function write_chunk( writer, data )
assert(writer, "msgpack writer should not be nil!!")
writer:write(TAG_START)
writer:write(msgpack.pack(data))
writer:write(TAG_END)
end
--------------------------------------------------------------------------------------------------
return {
read_chunk = read_chunk,
write_chunk = write_chunk,
}
--------------------------------------------------------------------------------------------------