Advertisement
guitarplayer616

Proper Serialization API [Immibis] [not really working]

Nov 27th, 2016
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.92 KB | None | 0 0
  1. -- Serialize it
  2. --local s = serialize(a)
  3. --print(s) -- prints gibberish
  4.  
  5. -- s is a string here - you can send it over modems or whatever (might not work with bundled cable rednet as I'm not sure if that preserves bit 7)
  6.  
  7. -- Deserialize it
  8. --local a2 = deserialize(s)
  9. --print(a2.b.c.d.test) -- should print 1
  10. --print(a2[a2.b.c][a2][a2.b.c].test) -- should print 2
  11.  
  12.  
  13. local function serializeInt(i)
  14.         local s = ""
  15.         repeat
  16.                 s = s .. string.char((i % 128) + ((i >= 128) and 128 or 0))
  17.                 i = math.floor(i / 128)
  18.         until i == 0
  19.         return s
  20. end
  21. -- returns int, next position
  22.  
  23.  
  24. local function deserializeInt(s,pos)
  25.         local k = pos
  26.         local i = 0
  27.         local m = 1
  28.         while true do
  29.                 local b = string.byte(s:sub(k,k))
  30.                 i = i + m * (b % 128)
  31.                 m = m * 128
  32.                 k = k + 1
  33.                 if b < 128 then break end
  34.         end
  35.         return i, k
  36. end
  37.  
  38. local nextid_key = {}
  39. local function serializeInternal(obj, seen)
  40.         if obj ~= nil and seen[obj] then
  41.                 return "06" .. serializeInt(seen[obj])
  42.         end
  43.         if type(obj) == "table" then
  44.                 local id = seen[nextid_key]
  45.                 seen[nextid_key] = id + 1
  46.                 seen[obj] = id
  47.  
  48.                 local s = "05"
  49.                 local ikeys = {}
  50.                 for k,v in ipairs(obj) do
  51.                         ikeys[k] = v
  52.                         s = s .. serializeInternal(v, seen)
  53.                 end
  54.                 s = s .. serializeInternal(nil, seen)
  55.                 for k,v in pairs(obj) do
  56.                         if ikeys[k] == nil then
  57.                                 s = s .. serializeInternal(k, seen) .. serializeInternal(v, seen)
  58.                         end
  59.                 end
  60.                 s = s .. serializeInternal(nil, seen)
  61.                 return s
  62.         elseif type(obj) == "number" then
  63.                 local ns = tostring(obj)
  64.                 return "04" .. serializeInt(ns:len()) .. ns
  65.         elseif type(obj) == "string" then
  66.                 return "03" .. serializeInt(obj:len()) .. obj
  67.         elseif type(obj) == "boolean" then
  68.                 if obj then
  69.                         return "01"
  70.                 else
  71.                         return "02"
  72.                 end
  73.         elseif type(obj) == "nil" then
  74.                 return "00"
  75.         elseif type(obj) == "userdata" then
  76.                 error("cannot serialize userdata")
  77.         elseif type(obj) == "thread" then
  78.                 error("cannot serialize threads")
  79.         elseif type(obj) == "function" then
  80.                 error("cannot serialize functions")
  81.         else
  82.                 error("unknown type: " .. type(obj))
  83.         end
  84. end
  85. function serialize(obj)
  86.         return serializeInternal(obj, {[nextid_key] = 0})
  87. end
  88. function deserialize(s)
  89.         local pos = 1
  90.         local seen = {}
  91.         local nextid = 0
  92.         local function internal()
  93.                 local tch = s:sub(pos,pos)
  94.                 local len
  95.                 pos = pos + 1
  96.                 if tch == "00" then
  97.                         return nil
  98.                 elseif tch == "01" then
  99.                         return true
  100.                 elseif tch == "02" then
  101.                         return false
  102.                 elseif tch == "03" then
  103.                         len, pos = deserializeInt(s, pos)
  104.                         local rv = s:sub(pos, pos+len-1)
  105.                         pos = pos + len
  106.                         return rv
  107.                 elseif tch == "04" then
  108.                         len, pos = deserializeInt(s, pos)
  109.                         local rv = s:sub(pos, pos+len-1)
  110.                         pos = pos + len
  111.                         return tonumber(rv)
  112.                 elseif tch == "05" then
  113.                         local id = nextid
  114.                         nextid = id + 1
  115.                         local t = {}
  116.                         seen[id] = t
  117.  
  118.                         local k = 1
  119.                         while true do
  120.                                 local v = internal()
  121.                                 if v == nil then break end
  122.                                 t[k] = v
  123.                                 k = k + 1
  124.                         end
  125.  
  126.                         while true do
  127.                                 local k = internal()
  128.                                 if k == nil then break end
  129.                                 local v = internal()
  130.                                 if v == nil then break end
  131.                                 t[k] = v
  132.                         end
  133.                         return t
  134.                 elseif tch == "06" then
  135.                         local id
  136.                         id, pos = deserializeInt(s, pos)
  137.                         return seen[id]
  138.                 else
  139.                         return nil
  140.                 end
  141.         end
  142.         return internal()
  143. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement