-- Light Unix I/O for Lua -- Copyright 2012 Rob Kendrick -- -- Distributed under the same terms as Lua itself (MIT). -- -- Simple serialiser that tries to make things small, for use for IPC. local type = type local format = string.format local tostring = tostring local error = error local concat = table.concat local dump = string.dump local function a(t, x) t[#t+1] = x end local keywords = { ["and"] = true, ["break"] = true, ["do"] = true, ["else"] = true, ["elseif"] = true, ["end"] = true, ["false"] = true, ["for"] = true, ["function"] = true, ["if"] = true, ["in"] = true, ["local"] = true, ["nil"] = true, ["not"] = true, ["or"] = true, ["repeat"] = true, ["return"] = true, ["then"] = true, ["true"] = true, ["until"] = true, ["while"] = true } local function serialise(x) local t = type(x) if t == "string" then return format("%q", x) elseif t == "function" then return format("loadstring(%q)", dump(x)) elseif t == "userdata" or t == "lightuserdata" then error "Cannot serialise userdata or lightuserdata" elseif t ~= "table" then return tostring(x) end local r = { "{" } -- first emit any sequence local k = 1 repeat local v = x[k] if v ~= nil then a(r, serialise(v)) a(r, ",") end k = k + 1 until v == nil -- emit other numerical keys for i, j in pairs(x) do if type(i) == "number" and i >= k then if r[#r] ~= "," then a(r, ",") end a(r, format("[%d]=%s", i, serialise(j))) a(r, ",") end end -- emit non-numeric keys for i, j in pairs(x) do local key local ti = type(i) if ti ~= "number" then if ti == "string" then key = format("%q", i) if not keywords[i] and i == format("%q", i):sub(2, -2) then key = i else key = "[" .. key .. "]" end elseif ti == "function" then key = "[loadstring(" .. format("%q", dump(i)) .. ")]" elseif ti == "table" then key = "[" .. serialise(i) .. "]" else error "unhandled key type" end a(r, format("%s=%s", key, serialise(j))) a(r, ",") end end if r[#r] == "," then r[#r] = nil end a(r, "}") return concat(r) end return { serialise = serialise }