I was explaining how to use serialize.lua to a friend, and I found myself somewhat befuddled by the output of serialize.save. Specifically, I don't understand why it must declare the table globally. Here's an example output now:
The expected use of this seems to be something like:
That's fine, but 'tbl' is now defined globally, potentially overwriting something in the global namespace. I might also only want to use it locally within a function, also. You might well say that I should be able to trust my own serialized data, but there's no guarantee that this is strictly staying within one plugin, or that I might change a global variable name in the future, and updated plugins will use the old state and overwrite that global.
My suggested patch would output:
This would allow you to directly control how the data is managed:
It also means that serialize.save doesn't need to know the name of the table to use. Since the loaded chunk has its own inner scope, you can use a specific name (in this case, tbl), and it will never clash, because the serialized table uses the "local" keyword. Thus, serialize.save can remove the "what" argument entirely.
Here's the patch. I don't have a diff tool handy, so I'll just paste by function.
Alternatively, if you want to keep backwards compatibility (I'm sure you do), ignore the above patch and just provide a serialize.load function like below
I'd prefer the serialize.save improvement, but this would at least make it more natural to decode:
You unfortunately still have to know the associated name ahead of time.
tbl = {}
tbl[1] = 1
tbl[2] = 2
tbl[3] = 3The expected use of this seems to be something like:
assert(loadstring(serialized_stuff))()That's fine, but 'tbl' is now defined globally, potentially overwriting something in the global namespace. I might also only want to use it locally within a function, also. You might well say that I should be able to trust my own serialized data, but there's no guarantee that this is strictly staying within one plugin, or that I might change a global variable name in the future, and updated plugins will use the old state and overwrite that global.
My suggested patch would output:
local tbl = {}
tbl[1] = 1
tbl[2] = 2
tbl[3] = 3
return tblThis would allow you to directly control how the data is managed:
-- if you want a global:
data = assert(loadstring(serialized_stuff))()
-- or a local:
local data = assert(loadstring(serialized_stuff))()It also means that serialize.save doesn't need to know the name of the table to use. Since the loaded chunk has its own inner scope, you can use a specific name (in this case, tbl), and it will never clash, because the serialized table uses the "local" keyword. Thus, serialize.save can remove the "what" argument entirely.
Here's the patch. I don't have a diff tool handy, so I'll just paste by function.
function save (v)
assert (v, "Must provide a valid variable for the 1st parameter!")
local out = {} -- output to this table
save_item ("tbl", v, out, 0, {}) -- do serialization
out[1] = "local " .. out[1]
table.insert(out, "return tbl")
return table.concat (out, "\n") -- turn into a string
end -- serialize.saveAlternatively, if you want to keep backwards compatibility (I'm sure you do), ignore the above patch and just provide a serialize.load function like below
function load(name, str)
local old = _G[name]
assert(type(name) == "string", "Argument 1 must be a string!")
assert(type(str) == "string", "Argument 2 must be a string!")
assert(loadstring(str))()
local val = _G[name]
_G[name] = old
return val
endI'd prefer the serialize.save improvement, but this would at least make it more natural to decode:
-- if you want a global:
data = serialize.load("name", serialized_stuff)
-- or a local:
local data = serialize.load("name", serialized_stuff)You unfortunately still have to know the associated name ahead of time.