如何将 Lua 中的元表序列化?

local binser = require "binser"

local log, floor, ceil, min, random = math.log, math.floor, math.ceil, math.min, math.random

local makeNode = function(value,size)
    return {
        value=value,
        next={},
        width={},
        size=size
    }
end

local End ={}
local NIL = makeNode(End,0)

local insert = function(self,value)
    local node, chain, stepsAtLevel = self.head, {}, {}
    for i=1, self.maxLevel do stepsAtLevel[i]=0 end
    for level = self.maxLevel, 1, -1 do
        while node.next[level] ~= NIL and node.next[level].value <= value do
            stepsAtLevel[level] = ( stepsAtLevel[level] or 0 ) + node.width[level]
            node = node.next[level]
            --print(level, stepsAtLevel[level],value)
        end
        chain[level]=node
    end

    local nodeLevel = min( self.maxLevel, - floor(log(random()) / log(2) ) )
    local newNode = makeNode( value,  nodeLevel)
    local steps, prevNode = 0
    for level= 1, nodeLevel do
        prevNode = chain[level]
        newNode.next[level] = prevNode.next[level]
        prevNode.next[level] = newNode
        newNode.width[level] = prevNode.width[level] - steps
        prevNode.width[level] = steps + 1
        steps = steps + stepsAtLevel[level]
    end
    for level = nodeLevel + 1, self.maxLevel do
        chain[level].width[level] = chain[level].width[level] +1
    end
    self.size = self.size + 1
end

 local first = function(self)
    return self.head.next[1].value
end

local tostring = function (self)
    local t = {}
    for k,v in self:ipairs() do table.insert(t,v) end
    return "( "..table.concat(t,", ").. " )"
end

local islMT = {
    __index = function(self,i)
        if type(i) ~= "number" then return end
        if i > self.size then return end
        local node = self.head

        for level=self.maxLevel, 1, -1 do
            while node.width[level] <= i do
                i = i - node.width[level]
                node = node.next[level]
            end
        end
        return node.value
    end,
    __tostring=tostring
}

local ipairs = function (self)
    local node, size = self.head.next[1] , self.size
    count = 0
    return function()
        value=node.value
        node = node.next[1]
        count = count+1
        return count <= size and count or nil, value
    end
end

math.randomseed(os.time())

local size = 预期大小 or 16
if not 预期大小 then
    预期大小 = 16
end

local maxLevel = floor( log(预期大小) / log(2) )
local head = makeNode("HEAD",maxLevel)
for i=1,maxLevel do
    head.next[i] = NIL
    head.width[i] = 1
end

local insdel = setmetatable( {
    size = 0,
    head = head,
    maxLevel = maxLevel,
    insert = insert,
    tostring = tostring,
    ipairs=ipairs,
    }, islMT
)

insdel:insert('foo')
print(insdel)

-- 如何序列化元表 insdel?这种方式失败了
local ser = binser.serialize(insdel)
insdel = binser.deserialize(ser)

insdel:insert('bar')
print(insdel)

我尝试了无数的序列化模块(如 serpent、json 和 pluto),但都无法处理元表。有人知道如何序列化元表吗?使用哪个模块来序列化/反序列化元表?

代码完整版已包括,binser 模块来自于 luarocks : https://luarocks.org/modules/bakpakin/binser

点赞