2019-11-09 16:00:49 +11:00
local serial = { }
local local_pairs = function ( tbl )
local mt = getmetatable ( tbl )
return ( mt and mt.__pairs or pairs ) ( tbl )
2019-01-12 20:48:03 +11:00
end
2020-05-12 10:57:13 +10:00
function serial . serialize ( value , af ) -- boolean -- string -- serialize *value* into a string. If *af* is true, allow functions. This breaks unserialization.
2019-11-09 16:00:49 +11:00
local kw = { [ " and " ] = true , [ " break " ] = true , [ " do " ] = true , [ " else " ] = true , [ " elseif " ] = true , [ " end " ] = true , [ " false " ] = true , [ " for " ] = true , [ " function " ] = true , [ " goto " ] = 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 id = " ^[%a_][%w_]*$ "
local ts = { }
local function s ( v , l )
local t = type ( v )
if t == " nil " then return " nil "
elseif t == " boolean " then return v and " true " or " false "
elseif t == " number " then
if v ~= v then return " 0/0 "
elseif v == math.huge then return " math.huge "
elseif v ==- math.huge then return " -math.huge "
else return tostring ( v ) end
elseif t == " string " then return string.format ( " %q " , v ) : gsub ( " \\ \n " , " \\ n " )
elseif t == " table " then
if ts [ v ] then error ( " tcyc " ) end
ts [ v ] = true
local i , r = 1 , nil
local f = table.pack ( local_pairs ( v ) )
for k , v in table.unpack ( f ) do
if r then r = r .. " , " .. ( ( " \n " .. string.rep ( " " , l ) ) or " " )
else r = " { " end
local tk = type ( k )
if tk == " number " and k == i then
i = i + 1
r = r .. s ( v , l + 1 )
2019-01-12 20:48:03 +11:00
else
2019-11-09 16:00:49 +11:00
if tk == " string " and not kw [ k ] and string.match ( k , id ) then r = r .. k
else r = r .. " [ " .. s ( k , l + 1 ) .. " ] " end
r = r .. " = " .. s ( v , l + 1 ) end end
ts [ v ] = nil
return ( r or " { " ) .. " } "
2019-12-16 14:35:11 +11:00
elseif t == " function " and af then
return tostring ( v )
2019-11-09 16:00:49 +11:00
else error ( " ut " .. t ) end end
return s ( value , 1 )
2019-01-12 20:48:03 +11:00
end
2020-05-12 10:57:13 +10:00
function serial . unserialize ( data ) -- string -- -- return *data*, but unserialized
2019-11-09 16:00:49 +11:00
checkArg ( 1 , data , " string " )
local result , reason = load ( " return " .. data , " =data " , _ , { math = { huge = math.huge } } )
if not result then return nil , reason end
local ok , output = pcall ( result )
if not ok then return nil , output end
return output
2019-01-12 20:48:03 +11:00
end
2019-11-09 16:00:49 +11:00
return serial